Ejemplo n.º 1
0
        /// <summary>
        /// Displays the received results, discarding existing data.
        /// </summary>
        /// <param name="lookupId">ID of lookup whose results are shown. If ID is smaller than last seen value, we don't show results.</param>
        /// <param name="entryProvider">The entry provider; ownership passed by caller to me.</param>
        /// <param name="results">Cedict lookup results to show.</param>
        /// <param name="script">Defines which script(s) to show.</param>
        /// <returns>True if results got shown; false if they're discarded because newer results are already on display.</returns>
        public bool SetResults(int lookupId,
                               ICedictEntryProvider entryProvider,
                               ReadOnlyCollection <CedictResult> results,
                               SearchScript script)
        {
#if DEBUG
            // Make us crash at bottom if first result "柏林" (comes up for "bolin")
            if (results.Count > 0)
            {
                CedictEntry entry = entryProvider.GetEntry(results[0].EntryId);
                if (entry.ChSimpl == "柏林")
                {
                    crashForTest = true;
                }
                else
                {
                    crashForTest = false;
                }
            }
#endif
            try
            {
                return(doSetResults(lookupId, entryProvider, results, script));
            }
            finally
            {
                if (entryProvider != null)
                {
                    entryProvider.Dispose();
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Ctor: annotated Hanzi
 /// </summary>
 public OneResultCtrl(string query, CedictAnnotation ann, ICedictEntryProvider prov, UiTones tones, bool isMobile)
 {
     this.query    = query;
     this.ann      = ann;
     this.prov     = prov;
     this.tones    = tones;
     this.isMobile = isMobile;
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Ctor: intialize immutable object.
 /// </summary>
 public CedictLookupResult(ICedictEntryProvider entryProvider,
     ReadOnlyCollection<CedictResult> results,
     SearchLang actualSearchLang)
 {
     EntryProvider = entryProvider;
     Results = results;
     ActualSearchLang = actualSearchLang;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Ctor: regular lookup result
 /// </summary>
 public OneResultCtrl(CedictResult res, ICedictEntryProvider prov,
                      UiScript script, UiTones tones, bool isMobile)
 {
     this.res      = res;
     this.prov     = prov;
     this.script   = script;
     this.tones    = tones;
     this.isMobile = isMobile;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Ctor: annotated Hanzi
 /// </summary>
 public EntryRenderer(string query, CedictAnnotation ann, ICedictEntryProvider prov,
                      UiTones tones)
 {
     this.query = query;
     this.ann   = ann;
     this.prov  = prov;
     this.tones = tones;
     this.hanim = true;
 }
Ejemplo n.º 6
0
 /// <summary>
 /// Ctor: intialize immutable object.
 /// </summary>
 public CedictLookupResult(ICedictEntryProvider entryProvider, string query,
                           List <CedictResult> results, List <CedictAnnotation> annotations, SearchLang actualSearchLang)
 {
     Query            = query;
     EntryProvider    = entryProvider;
     Results          = new ReadOnlyCollection <CedictResult>(results);
     Annotations      = new ReadOnlyCollection <CedictAnnotation>(annotations);
     ActualSearchLang = actualSearchLang;
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Ctor: regular lookup result
 /// </summary>
 public EntryRenderer(CedictResult res, ICedictEntryProvider prov,
                      UiScript script, UiTones tones)
 {
     this.res              = res;
     this.prov             = prov;
     this.script           = script;
     this.tones            = tones;
     this.hanim            = true;
     this.dimIdenticalTrad = true;
 }
Ejemplo n.º 8
0
        protected void Page_Load(object sender, EventArgs e)
        {
            // Add CSS files
            Master.AddCss("tooltipster.css");
            Master.AddCss("style.css");
            Master.AddCss("entry.css");
            Master.AddCss("lookup.css");
            // Add JS includes
            Master.AddJS("jquery.tooltipster.min.js", true);
            Master.AddJS("common.js", false);
            Master.AddJS("lookup.js", false);
            Master.AddJS("strokeanim.js", false);

            if (string.IsNullOrEmpty(Request.Params["query"]))
            {
                loadStatic("Welcome");
                return;
            }

            string query = Request.Params["query"].Replace('+', ' ');

            txtSearch.Value = query;
            CedictLookupResult lr;

            using (SqlDict.Query q = new SqlDict.Query())
            {
                lr = q.Lookup(query);
            }
            // No results
            if (lr.Results.Count == 0 && lr.Annotations.Count == 0)
            {
                loadStatic("NoResults");
                return;
            }
            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, false);
                resultsHolder.Controls.Add(resCtrl);
            }
            // SOA BOX
            soaBox.Visible = true;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Ctor: takes data to display.
        /// </summary>
        /// <param name="owner">Zen control that owns me.</param>
        /// <param name="tprov">Localized display text provider.</param>
        /// <param name="lookupThroughLink">Delegate to call when user initiates lookup by clicking on a link.</param>
        /// <param name="getEntry">Delegate to call when an entry must be retrieved (for "copy" context menu).</param>
        /// <param name="entryProvider">Dictionary entry provider.</param>
        /// <param name="cr">The lookup result this control will show.</param>
        /// <param name="maxHeadLength">Longest headword in full results list.</param>
        /// <param name="script">Scripts to show in headword.</param>
        /// <param name="odd">Odd/even position in list, for alternating BG color.</param>
        public OneResultControl(ZenControlBase owner, float scale, ITextProvider tprov,
                                LookupThroughLinkDelegate lookupThroughLink,
                                ParentPaintDelegate parentPaint, GetEntryDelegate getEntry,
                                ICedictEntryProvider entryProvider, CedictResult cr,
                                SearchScript script, bool last)
            : base(owner)
        {
            this.scale             = scale;
            this.tprov             = tprov;
            this.lookupThroughLink = lookupThroughLink;
            this.parentPaint       = parentPaint;
            this.getEntry          = getEntry;
            this.entry             = entryProvider.GetEntry(cr.EntryId);
            this.res            = cr;
            this.analyzedScript = script;
            this.last           = last;

            padLeft   = (int)(5.0F * scale);
            padTop    = (int)(4.0F * scale);
            padBottom = (int)(8.0F * scale);
            padMid    = (int)(20.0F * scale);
            padRight  = (int)(10.0F * scale);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// See <see cref="SetResults"/>.
        /// </summary>
        private bool doSetResults(int lookupId,
                                  ICedictEntryProvider entryProvider,
                                  ReadOnlyCollection <CedictResult> results,
                                  SearchScript script)
        {
            lock (displayIdLO)
            {
                // If we're already too late, don't bother changing display.
                if (displayId > lookupId)
                {
                    return(false);
                }
                displayId = lookupId;
                // Empty result set - special handling
                if (results.Count == 0)
                {
                    lock (resCtrlsLO)
                    {
                        doDisposeResultControls();
                        txtResCount = tprov.GetString("ResultsCountNone");
                        setScrollbarVisibility(false);
                    }
                    // Render
                    doFade(false);
                    MakeMePaint(false, RenderMode.Invalidate);
                    return(true);
                }
            }

            // Decide if we first try with scrollbar visible or not
            // This is a very rough heuristics (10 results or more), but doesn't matter
            // Recalc costs much if there are many results, and the number covers that safely
            bool sbarVisible = results.Count > 10;

            // Content rectangle height and width
            int cw, ch;

            getContentSize(sbarVisible, out cw, out ch);

            // Create new result controls. At this point, not overwriting old ones!
            // This is the cycle that takes *long*.
            List <OneResultControl> newCtrls = new List <OneResultControl>(results.Count);
            int y = 0;

            using (Bitmap bmp = new Bitmap(1, 1))
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    bool canceled = false;
                    for (int rix = 0; rix != results.Count; ++rix)
                    {
                        CedictResult     cr  = results[rix];
                        OneResultControl orc = new OneResultControl(null, Scale, tprov,
                                                                    onLookupFromCtrl, onPaintFromCtrl, onGetEntry,
                                                                    entryProvider, cr, script, rix == results.Count - 1);
                        orc.Analyze(g, cw);
                        // Cannot use RelLocation b/c control has no parent yet
                        orc.AbsLocation = new Point(AbsLeft + 1, AbsTop + y + 1);
                        y += orc.Height;
                        newCtrls.Add(orc);
                        // At any point, if we realize lookup ID has changed, we stop
                        // This can happen if a later, quick lookup completes and shows results before us
                        // Checking integers is atomic, no locking
                        if (displayId > lookupId)
                        {
                            canceled = true; break;
                        }
                    }
                    if (canceled)
                    {
                        foreach (OneResultControl orc in newCtrls)
                        {
                            orc.Dispose();
                        }
                        return(false);
                    }
                }
            // OK, last chance to change our mind about showing results.
            // The rest is synchronized - but it's also fast
            lock (displayIdLO)
            {
                if (displayId > lookupId)
                {
                    return(false);
                }
                displayId = lookupId;
                // Rest must be invoked on GUI. Otherwise, as we're adding children,
                // Collections are modified that are also accessed by paint in a resize event handler etc.
                InvokeOnForm((MethodInvoker) delegate
                {
                    // Stop any scrolling that may be going on. Cannot scroll what's being replaced.
                    if (sbar.Parent == this)
                    {
                        sbar.StopAnyScrolling();
                    }
                    // Prevent any painting from worker threads - also accesses collection we're changing
                    lock (resCtrlsLO)
                    {
                        // Get rid of old result controls, remember/own new ones
                        doDisposeResultControls();
                        resCtrls = newCtrls;
                        foreach (OneResultControl orc in resCtrls)
                        {
                            AddChild(orc);
                        }
                        // Actually show or hide scrollbar as per original decision
                        setScrollbarVisibility(sbarVisible);
                        // Now, by the time we're here, size may have changed
                        // That is unlikely, but then we got to re-layout stuff
                        int cwNew, chNew;
                        getContentSize(sbarVisible, out cwNew, out chNew);
                        if (cwNew != cw || chNew != ch)
                        {
                            reAnalyzeResultsDisplay();
                        }
                        else
                        {
                            // Everything as big as it used to be...
                            // Change our mind about scrollbar?
                            cw = showOrHideScrollbar();
                        }
                    }
                    // Results count text
                    if (resCtrls.Count == 1)
                    {
                        txtResCount = tprov.GetString("ResultsCountOne");
                    }
                    else
                    {
                        txtResCount = tprov.GetString("ResultsCountN");
                        txtResCount = string.Format(txtResCount, resCtrls.Count);
                    }
                    // Update first visible control's index
                    updateFirstVisibleIdx();
                    // Render
                    doFade(false);
                    MakeMePaint(false, RenderMode.Invalidate);
                });
                // Done.
                return(true);
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Ctor: takes data to display.
        /// </summary>
        /// <param name="owner">Zen control that owns me.</param>
        /// <param name="tprov">Localized display text provider.</param>
        /// <param name="lookupThroughLink">Delegate to call when user initiates lookup by clicking on a link.</param>
        /// <param name="getEntry">Delegate to call when an entry must be retrieved (for "copy" context menu).</param>
        /// <param name="entryProvider">Dictionary entry provider.</param>
        /// <param name="cr">The lookup result this control will show.</param>
        /// <param name="maxHeadLength">Longest headword in full results list.</param>
        /// <param name="script">Scripts to show in headword.</param>
        /// <param name="odd">Odd/even position in list, for alternating BG color.</param>
        public OneResultControl(ZenControlBase owner, float scale, ITextProvider tprov,
            LookupThroughLinkDelegate lookupThroughLink,
            ParentPaintDelegate parentPaint, GetEntryDelegate getEntry,
            ICedictEntryProvider entryProvider, CedictResult cr,
            SearchScript script, bool last)
            : base(owner)
        {
            this.scale = scale;
            this.tprov = tprov;
            this.lookupThroughLink = lookupThroughLink;
            this.parentPaint = parentPaint;
            this.getEntry = getEntry;
            this.entry = entryProvider.GetEntry(cr.EntryId);
            this.res = cr;
            this.analyzedScript = script;
            this.last = last;

            padLeft = (int)(5.0F * scale);
            padTop = (int)(4.0F * scale);
            padBottom = (int)(8.0F * scale);
            padMid = (int)(20.0F * scale);
            padRight = (int)(10.0F * scale);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// See <see cref="SetResults"/>.
        /// </summary>
        private bool doSetResults(int lookupId,
            ICedictEntryProvider entryProvider,
            ReadOnlyCollection<CedictResult> results,
            SearchScript script)
        {
            lock (displayIdLO)
            {
                // If we're already too late, don't bother changing display.
                if (displayId > lookupId) return false;
                displayId = lookupId;
                // Empty result set - special handling
                if (results.Count == 0)
                {
                    lock (resCtrlsLO)
                    {
                        doDisposeResultControls();
                        txtResCount = tprov.GetString("ResultsCountNone");
                        setScrollbarVisibility(false);
                    }
                    // Render
                    doFade(false);
                    MakeMePaint(false, RenderMode.Invalidate);
                    return true;
                }
            }

            // Decide if we first try with scrollbar visible or not
            // This is a very rough heuristics (10 results or more), but doesn't matter
            // Recalc costs much if there are many results, and the number covers that safely
            bool sbarVisible = results.Count > 10;

            // Content rectangle height and width
            int cw, ch;
            getContentSize(sbarVisible, out cw, out ch);

            // Create new result controls. At this point, not overwriting old ones!
            // This is the cycle that takes *long*.
            List<OneResultControl> newCtrls = new List<OneResultControl>(results.Count);
            int y = 0;
            using (Bitmap bmp = new Bitmap(1, 1))
            using (Graphics g = Graphics.FromImage(bmp))
            {
                bool canceled = false;
                for (int rix = 0; rix != results.Count; ++rix)
                {
                    CedictResult cr = results[rix];
                    OneResultControl orc = new OneResultControl(null, Scale, tprov,
                        onLookupFromCtrl, onPaintFromCtrl, onGetEntry,
                        entryProvider, cr, script, rix == results.Count - 1);
                    orc.Analyze(g, cw);
                    // Cannot use RelLocation b/c control has no parent yet
                    orc.AbsLocation = new Point(AbsLeft + 1, AbsTop + y + 1);
                    y += orc.Height;
                    newCtrls.Add(orc);
                    // At any point, if we realize lookup ID has changed, we stop
                    // This can happen if a later, quick lookup completes and shows results before us
                    // Checking integers is atomic, no locking
                    if (displayId > lookupId) { canceled = true; break; }
                }
                if (canceled)
                {
                    foreach (OneResultControl orc in newCtrls) orc.Dispose();
                    return false;
                }
            }
            // OK, last chance to change our mind about showing results.
            // The rest is synchronized - but it's also fast
            lock (displayIdLO)
            {
                if (displayId > lookupId) return false;
                displayId = lookupId;
                // Rest must be invoked on GUI. Otherwise, as we're adding children,
                // Collections are modified that are also accessed by paint in a resize event handler etc.
                InvokeOnForm((MethodInvoker)delegate
                {
                    // Stop any scrolling that may be going on. Cannot scroll what's being replaced.
                    if (sbar.Parent == this) sbar.StopAnyScrolling();
                    // Prevent any painting from worker threads - also accesses collection we're changing
                    lock (resCtrlsLO)
                    {
                        // Get rid of old result controls, remember/own new ones
                        doDisposeResultControls();
                        resCtrls = newCtrls;
                        foreach (OneResultControl orc in resCtrls) AddChild(orc);
                        // Actually show or hide scrollbar as per original decision
                        setScrollbarVisibility(sbarVisible);
                        // Now, by the time we're here, size may have changed
                        // That is unlikely, but then we got to re-layout stuff
                        int cwNew, chNew;
                        getContentSize(sbarVisible, out cwNew, out chNew);
                        if (cwNew != cw || chNew != ch) reAnalyzeResultsDisplay();
                        else
                        {
                            // Everything as big as it used to be...
                            // Change our mind about scrollbar?
                            cw = showOrHideScrollbar();
                        }
                    }
                    // Results count text
                    if (resCtrls.Count == 1) txtResCount = tprov.GetString("ResultsCountOne");
                    else
                    {
                        txtResCount = tprov.GetString("ResultsCountN");
                        txtResCount = string.Format(txtResCount, resCtrls.Count);
                    }
                    // Update first visible control's index
                    updateFirstVisibleIdx();
                    // Render
                    doFade(false);
                    MakeMePaint(false, RenderMode.Invalidate);
                });
                // Done.
                return true;
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Displays the received results, discarding existing data.
 /// </summary>
 /// <param name="lookupId">ID of lookup whose results are shown. If ID is smaller than last seen value, we don't show results.</param>
 /// <param name="entryProvider">The entry provider; ownership passed by caller to me.</param>
 /// <param name="results">Cedict lookup results to show.</param>
 /// <param name="script">Defines which script(s) to show.</param>
 /// <returns>True if results got shown; false if they're discarded because newer results are already on display.</returns>
 public bool SetResults(int lookupId,
     ICedictEntryProvider entryProvider,
     ReadOnlyCollection<CedictResult> results,
     SearchScript script)
 {
     #if DEBUG
     // Make us crash at bottom if first result "柏林" (comes up for "bolin")
     if (results.Count > 0)
     {
         CedictEntry entry = entryProvider.GetEntry(results[0].EntryId);
         if (entry.ChSimpl == "柏林") crashForTest = true;
         else crashForTest = false;
     }
     #endif
     try
     {
         return doSetResults(lookupId, entryProvider, results, script);
     }
     finally
     {
         if (entryProvider != null) entryProvider.Dispose();
     }
 }
Ejemplo n.º 14
0
        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);
                }
            }
        }