private DialogueBoxVer2 DisplayDialogueBox2()
        {
            var richText    = "";
            var listOptions = new List <DialogueOption>();

            _currentNode.RefreshConditionsData();
            if (_currentNode.HasNext())
            {
                _currentNode.GetNextPage(out richText, ref listOptions);
            }

            var requiredComponent = GameObject.FindWithTag("DialogueGui").GetRequiredComponent <DialogueBoxVer2>();

            requiredComponent.SetVisible(true);
            requiredComponent.SetDialogueText(richText, listOptions);
            if (_characterName == "")
            {
                requiredComponent.SetNameFieldVisible(false);
            }
            else
            {
                requiredComponent.SetNameFieldVisible(true);
                requiredComponent.SetNameField(TextTranslation.Translate(_characterName));
            }

            return(requiredComponent);
        }
Exemple #2
0
        public override void OnReceiveRemote(bool server, ConversationMessage message)
        {
            if (!QSBCore.HasWokenUp)
            {
                return;
            }
            switch (message.EnumValue)
            {
            case ConversationType.Character:
                var translated = TextTranslation.Translate(message.Message).Trim();
                translated = Regex.Replace(translated, @"<[Pp]ause=?\d*\.?\d*\s?\/?>", "");
                ConversationManager.Instance.DisplayCharacterConversationBox(message.ObjectId, translated);
                break;

            case ConversationType.Player:
                ConversationManager.Instance.DisplayPlayerConversationBox((uint)message.ObjectId, message.Message);
                break;

            case ConversationType.CloseCharacter:
                if (message.ObjectId == -1)
                {
                    break;
                }
                var tree = QSBWorldSync.OldDialogueTrees[message.ObjectId];
                UnityEngine.Object.Destroy(ConversationManager.Instance.BoxMappings[tree]);
                break;

            case ConversationType.ClosePlayer:
                UnityEngine.Object.Destroy(QSBPlayerManager.GetPlayer((uint)message.ObjectId).CurrentDialogueBox);
                break;
            }
        }
Exemple #3
0
        public static void LoadControlTranslations(Control.ControlCollection Controls)
        {
            foreach (Control c in Controls)
            {
                if (c is MetroFramework.Controls.MetroLabel || c is MetroFramework.Controls.MetroButton)
                {
                    TextTranslation str = TextTranslations.Where(x => x.Id == c.Name).FirstOrDefault();
                    if (str != null && str.Text.Length > 0)
                    {
                        c.Text = str.Text;
                    }
                    else
                    {
                        if (c.Text != "-")
                        {
                            c.Text = c.Name;
                        }
                    }
                }

                if (c.HasChildren)
                {
                    LoadControlTranslations(c.Controls);
                }
            }
        }
        public override void OnReceiveRemote()
        {
            switch (Value)
            {
            case ConversationType.Character:
                var translated = TextTranslation.Translate(Message).Trim();
                translated = Regex.Replace(translated, @"<[Pp]ause=?\d*\.?\d*\s?\/?>", "");
                ConversationManager.Instance.DisplayCharacterConversationBox(Id, translated);
                break;

            case ConversationType.Player:
                ConversationManager.Instance.DisplayPlayerConversationBox((uint)Id, Message);
                break;

            case ConversationType.CloseCharacter:
                if (Id == -1)
                {
                    break;
                }

                var tree = QSBWorldSync.OldDialogueTrees[Id];
                Object.Destroy(ConversationManager.Instance.BoxMappings[tree]);
                break;

            case ConversationType.ClosePlayer:
                Object.Destroy(QSBPlayerManager.GetPlayer((uint)Id).CurrentDialogueBox);
                break;
            }
        }
        private void OnTranslateString(object sender, StringTranslationEventArgs e)
        {
            string inputText = e.Text;

            if (string.IsNullOrEmpty(inputText))
            {
                return;
            }

            if (inputText.StartsWith(TEMPLATE_STRING_PREFIX))
            {
                if (!isRetranslating)
                {
                    e.Translation = inputText;
                    return;
                }
                inputText = inputText.Substring(1);
            }

            bool isAudioClipName = inputText.StartsWith(Subtitles.AUDIOCLIP_PREFIX);

            if (isAudioClipName)
            {
                inputText = inputText.Substring(Subtitles.AUDIOCLIP_PREFIX.Length);
            }

            TextTranslation translation = Memory.GetTextTranslation(inputText);

            if (translation.Result == TranslationResult.Ok || isRetranslating && translation.Result == TranslationResult.NotFound)
            {
                e.Translation = translation.Text;
            }

            if (e.Type == StringType.Template && e.Translation != null)
            {
                e.Translation = TEMPLATE_STRING_PREFIX + e.Translation;
                return;
            }

            if (translation.Result == TranslationResult.Ok || translation.Result == TranslationResult.Translated)
            {
                return;
            }

            if (!isAudioClipName)
            {
                if (e.Type != StringType.Template) // Don't put templates to clipboard -- let the game replace the values first
                {
                    Clipboard.AddText(inputText, CurrentLevel);
                }
                // Still going to dump, since templates are useful to translators, but not all translateable strings are templates
                Logger.DumpLine(inputText, CurrentLevel);
            }
            else
            {
                e.Translation = inputText;
                Logger.DumpLine(inputText, CurrentLevel, DumpType.Voices);
            }
        }
        public static UITextType AddToUITable(string text)
        {
            var table = TextTranslation.Get().m_table;
            var key   = table.theUITable.Keys.Max() + 1;

            table.theUITable[key] = text;
            return((UITextType)key);
        }
        private async void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox langComboBox = sender as ComboBox;

            if (langComboBox != null && langComboBox.SelectedIndex > -1)
            {
                if (textTransDataGrid.SelectedItem != null)
                {
                    int indexOfItemInTextTranslationList = TextTranslationList.IndexOf(textTransDataGrid.SelectedItem as TextTranslation);
                    if (TextTranslationList[indexOfItemInTextTranslationList].IsEnabled)
                    {
                        string  selectedLanguageCode = langComboBox.SelectedItem.ToString();
                        DataRow languageDetail       = await dbCon.GetDataRow("LanguageReference", new DataRow("LanguageCode", selectedLanguageCode));

                        if (languageDetail.HasData && languageDetail.Error == ERROR.NoError)
                        {
                            string selectedLanguageName = languageDetail.Get("LanguageName").ToString();

                            TextDisplayWindow textDisplayWindow = new TextDisplayWindow(selectedLanguageCode, selectedLanguageName);
                            textDisplayWindow.ShowDialog();

                            if (textDisplayWindow.DialogResult.HasValue && textDisplayWindow.DialogResult.Value)
                            {
                                string textTemplate = textDisplayWindow.DisplayText;

                                TextTranslationList[indexOfItemInTextTranslationList].LanguageName = selectedLanguageName;
                                TextTranslationList[indexOfItemInTextTranslationList].IsEnabled    = false;
                                TextTranslationList[indexOfItemInTextTranslationList].TextTemplate = textTemplate;
                                textTransDataGrid.CurrentCell = new DataGridCellInfo(textTransDataGrid.SelectedItem, textTransDataGrid.Columns[0]);
                                textTransDataGrid.CommitEdit();

                                TextTranslation tt      = new TextTranslation();
                                List <string>   excepts = new List <string>();
                                foreach (TextTranslation ttData in TextTranslationList)
                                {
                                    if (!string.IsNullOrWhiteSpace(ttData.LanguageCode))
                                    {
                                        excepts.Add(ttData.LanguageCode);
                                    }
                                }
                                tt.LanguageList = await LoadLanguageList(excepts.ToArray());

                                if (tt.LanguageList.Count > 0)
                                {
                                    TextTranslationList.Add(tt);
                                }
                            }
                            else
                            {
                                textTransDataGrid.BeginEdit();
                                textTransDataGrid.CancelEdit();
                            }
                        }
                        textTransDataGrid.SelectedIndex = -1;
                    }
                }
            }
        }
Exemple #8
0
        static void TopWindow_Load(object sender, EventArgs e)
        {
            ToolStripMenuItem svgMenu = new ToolStripMenuItem();

            svgMenu.Text   = TextTranslation.Translate("Import SVG file(s)");
            svgMenu.Click += svgMenu_Click;

            CamBamUI.MainUI.Menus.mnuPlugins.DropDownItems.Add(svgMenu);
        }
        private async void App_GotSpeech(object sender, GotSpeechTextEventArgs e)
        {
            TranslationClient client = new TranslationClient();

            TextTranslation trans = client.Translate(langCode, e.Text);

            Translation.Text = trans.Text;

            await SpeakNow(trans.Text);
        }
        public void Awake()
        {
            Application.runInBackground = true;

            _thisInstance = this;

            var instance = TextTranslation.Get().GetValue <TextTranslation.TranslationTable>("m_table");

            instance.theUITable[(int)UITextType.PleaseUseController] =
                "<color=orange>Quantum Space Buddies</color> is best experienced with friends...";
        }
Exemple #11
0
    public void Proc()
    {
        TextTranslation trans = null;

        Log.Note("Epub2Comment");

        if (!string.IsNullOrEmpty(glossaryDocPath))
        {
            trans = new GlossaryImportation(glossaryDocPath);
        }
        else if (castBlackTranslatingMagic)
        {
            trans = new BlackTranslationMagic();
        }
        if (trans != null)
        {
            Log.Note("Text Translation Method: " + trans.ToString());
        }



        Directory.CreateDirectory(output_path);
        try
        {
            if (epub.toc.mediaType == "application/x-dtbncx+xml")
            {
                Parse2();
            }
            else
            {
                Parse3();
            }
        }
        catch (Exception)
        {
            Log.Warn("尝试序列化失败。");
            tocTree = null;
        }

        var plain = GetPlainStruct();

        for (int i = 0; i < plain.Length; i++)
        {
            var t   = epub.spine[i].item.GetFile() as TextEpubItemFile;
            var txt = Html2Comment.ProcXHTML(t.text, trans);
            var p   = output_path + "i" + Util.Number(i, 2) + "_" + Path.GetFileNameWithoutExtension(t.fullName) + Util.FilenameCheck(plain[i]) + ".txt";
            File.WriteAllText(p, txt);
            Log.Note(p);
        }
    }
Exemple #12
0
        private async Task InitializeRotation()
        {
            DisplayMessage("ENG");
            rotateTimer           = new Timer(ShowText.RotateInSeconds * 1000);
            rotateTimer.AutoReset = false;
            rotateTimer.Elapsed  += RotateTimer_Elapsed;
            rotateTimer.Start();
            DataList textTranslationList = await dbCon.GetDataList("TextTranslation", new DataRow("TextTemplateId", ShowText.TextTemplateId));

            if (textTranslationList.HasData && textTranslationList.Error == ERROR.NoError)
            {
                foreach (DataRow textTranslationRow in textTranslationList)
                {
                    TextTranslation textTranslation = new TextTranslation();
                    PropertyInfo[]  properties      = textTranslation.GetType().GetProperties();
                    foreach (PropertyInfo property in properties)
                    {
                        if (textTranslationRow.ContainKey(property.Name))
                        {
                            property.SetValue(textTranslation, textTranslationRow.Get(property.Name));
                        }
                    }
                    TextTranslationList.Add(textTranslation);
                }
                foreach (TextTranslation textTranslation in TextTranslationList)
                {
                    DataRow originAirportTranslation = await dbCon.GetDataRow("AirportTranslation",
                                                                              new DataRow("AirportCode", ShowText.OriginCode, "LanguageCode", textTranslation.LanguageCode));

                    if (originAirportTranslation.HasData && originAirportTranslation.Error == ERROR.NoError)
                    {
                        AirportTranslation airportTranslation = new AirportTranslation();
                        airportTranslation = AddDataToProperty(typeof(AirportTranslation), originAirportTranslation) as AirportTranslation;
                        OriginAirportTranslationList.Add(airportTranslation);
                    }

                    DataRow destinationAirportTranslation = await dbCon.GetDataRow("AirportTranslation",
                                                                                   new DataRow("AirportCode", ShowText.DestinationCode, "LanguageCode", textTranslation.LanguageCode));

                    if (destinationAirportTranslation.HasData && destinationAirportTranslation.Error == ERROR.NoError)
                    {
                        AirportTranslation airportTranslation = new AirportTranslation();
                        airportTranslation = AddDataToProperty(typeof(AirportTranslation), destinationAirportTranslation) as AirportTranslation;
                        DestinationAirportTranslationList.Add(airportTranslation);
                    }
                }
                indexOfTranslation++;
            }
        }
        private async void Translate_Clicked(object sender, EventArgs e)
        {
            if (TextToTranslate.Text == "")
            {
                return;
            }

            TranslationClient client = new TranslationClient();

            TextTranslation trans = client.Translate(langCode, TextToTranslate.Text);

            Translation.Text = trans.Text;

            await SpeakNow(trans.Text);
        }
Exemple #14
0
        public static void YotogiKagManager_Tag(YotogiKagManager manager, KagTagSupport kagTag)
        {
            try
            {
                var list = kagTag.GetTagList();

                Logger.Log(LogLevel.Debug, $"[Yotogi] Kag Tag({list["tagname"]})");

                switch (list["tagname"])
                {
                case "talk":
                case "talkrepeat":
                    foreach (var tag in list)
                    {
                        Logger.Log(LogLevel.Debug, $"[Yotogi] Kag Tag {tag.Key}:{tag.Value}");
                    }
                    yotogiTagEventArgs = new YotogiKagHitRetEventArgs(list["voice"] + ".ogg");
                    yotogiTagEventArgs.TagCallStack.Add(kagTag);
                    break;

                case "hitret":
                    if (yotogiTagEventArgs == null)
                    {
                        return;
                    }

                    yotogiTagEventArgs.Text = manager.kag.GetText();

                    var args = new TextTranslationEventArgs(manager.kag.GetText(), TextType.Text, TextSource.Yotogi);
                    TextTranslation?.Invoke(manager, args);

                    if (args.Translation != null)
                    {
                        yotogiTagEventArgs.Translation = args.Translation;
                    }

                    yotogiTagEventArgs.TagCallStack.Add(kagTag);
                    YotogiKagHitRet?.Invoke(manager, yotogiTagEventArgs);
                    yotogiTagEventArgs = null;
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Log(LogLevel.Error, ex);
                throw;
            }
        }
Exemple #15
0
 public static void ScheduleAPI_InfoReplace(int tag, ref int nightWorkId, ref String value)
 {
     try
     {
         var args = new TextTranslationEventArgs(value, (TextType)tag, TextSource.ScheduleAPI);
         TextTranslation?.Invoke(null, args);
         if (args.Translation != null)
         {
             value = args.Translation;
         }
     }
     catch (Exception ex)
     {
         Logger.Log(LogLevel.Error, ex);
         throw;
     }
 }
Exemple #16
0
 public static void ScriptManager_ReplaceCharaName(int tag, ref String value)
 {
     try
     {
         var args = new TextTranslationEventArgs(value, (TextType)tag, TextSource.ScriptManager);
         TextTranslation?.Invoke(null, args);
         if (args.Translation != null)
         {
             value = args.Translation;
         }
     }
     catch (Exception ex)
     {
         Logger.Log(LogLevel.Error, ex);
         throw;
     }
 }
        protected override void TestMappings(PersistenceSpecification <Text> specification)
        {
            Assertion.NotNull(specification);

            var textsCategory = new TextsCategory("category.name");
            var person        = new Person("person.nameFirst", "person.nameLast");
            var translation   = new TextTranslation("ru", "translation.name", "translation.text");

            specification.TransactionalSave(textsCategory);
            specification.TransactionalSave(person);
            specification.TransactionalSave(translation);

            base.TestMappings(specification);
            specification.CheckReference(mapping => mapping.Category, textsCategory);
            specification.CheckReference(mapping => mapping.Person, person);
            specification.CheckBag(mapping => mapping.Translations, new[] { translation });
        }
Exemple #18
0
 public static void FreeScene_UI_FreeScene_Start(int tag, ref String value, ref Action endAction)
 {
     try
     {
         var args = new TextTranslationEventArgs(value, (TextType)tag, TextSource.FreeSceneUI);
         TextTranslation?.Invoke(null, args);
         if (args.Translation != null)
         {
             value = args.Translation;
         }
     }
     catch (Exception ex)
     {
         Logger.Log(LogLevel.Error, ex);
         throw;
     }
 }
Exemple #19
0
 public static void UILabel_ProcessText(int tag, UILabel control, ref String value)
 {
     try
     {
         var args = new TextTranslationEventArgs(value, (TextType)tag, TextSource.UILabel);
         TextTranslation?.Invoke(control, args);
         if (args.Translation != null)
         {
             value = args.Translation;
         }
     }
     catch (Exception ex)
     {
         Logger.Log(LogLevel.Error, ex);
         throw;
     }
 }
        private async void InitializeTextTranslationList()
        {
            TextTranslationList = new ObservableCollection <TextTranslation>();
            TextTranslationList.CollectionChanged += TextTranslationList_CollectionChanged;
            textTransDataGrid.ItemsSource          = TextTranslationList;

            //Add existing translation to datagrid
            //Add uncommit language translation to last row as a combobox itemssource
            TextTranslation tt;
            List <string>   excepts = new List <string>();

            if (Status == STATUS.EDIT)
            {
                DataList list = await dbCon.GetDataList("TextTranslation", new DataRow("TextTemplateId", TextTemplateId));

                if (list.HasData && list.Error == ERROR.NoError)
                {
                    foreach (DataRow row in list)
                    {
                        tt = new TextTranslation
                        {
                            TextTranslationId = (Guid)row.Get("TextTranslationId"),
                            TextTemplateId    = (Guid)row.Get("TextTemplateId"),
                            LanguageCode      = row.Get("LanguageCode").ToString(),
                            LanguageName      = (await dbCon.GetDataRow("LanguageReference",
                                                                        new DataRow("LanguageCode", row.Get("LanguageCode").ToString()))).Get("LanguageName").ToString(),
                            TextTemplate = row.Get("TextTemplate").ToString(),
                            IsEnabled    = false
                        };
                        TextTranslationList.Add(tt);
                        excepts.Add(row.Get("LanguageCode").ToString());
                    }
                }
            }
            tt = new TextTranslation();
            tt.LanguageList = await LoadLanguageList(excepts.ToArray());

            if (tt.LanguageList.Count > 0)
            {
                TextTranslationList.Add(tt);
            }
        }
Exemple #21
0
        private static void on_window_shown(object sender, EventArgs e)
        {
            ThisApplication.TopWindow.Shown -= on_window_shown;

            ToolStripButton button;

            button             = new ToolStripButton();
            button.ToolTipText = TextTranslation.Translate(profile_mop_name);
            button.Click      += profile_mop_onclick;
            button.Image       = resources.cam_trochoprof1;

            insert_in_toolbar(button);

            button             = new ToolStripButton();
            button.ToolTipText = TextTranslation.Translate(pocket_mop_name);
            button.Click      += pocket_mop_onclick;
            button.Image       = resources.cam_trochopock1;

            insert_in_toolbar(button);
        }
        private void EditDisplayText()
        {
            int indexOfSelectedItem = textTransDataGrid.SelectedIndex;

            if (indexOfSelectedItem > -1 && !string.IsNullOrWhiteSpace((textTransDataGrid.SelectedItem as TextTranslation).LanguageCode))
            {
                TextTranslation   tt = TextTranslationList[indexOfSelectedItem];
                TextDisplayWindow textDisplayWindow = new TextDisplayWindow(tt.LanguageCode, tt.LanguageName, tt.TextTemplate);
                textDisplayWindow.ShowDialog();
                if (textDisplayWindow.DialogResult.HasValue && textDisplayWindow.DialogResult.Value)
                {
                    string textTemplate = textDisplayWindow.DisplayText;
                    TextTranslationList[indexOfSelectedItem].TextTemplate = textTemplate;
                }
                else
                {
                    textTransDataGrid.SelectedIndex = -1;
                }
            }
        }
Exemple #23
0
 public void AddTranslateField(TextTranslation textField)
 {
     textFields.Add(textField);
 }
Exemple #24
0
        public ImportSVG()
        {
            InitializeComponent();

            label1.Text = TextTranslation.Translate("Drop here the SVG file(s).");
        }
        public static void ReplaceUI(UITextType key, string text)
        {
            var table = TextTranslation.Get().m_table;

            table.theUITable[(int)key] = text;
        }
Exemple #26
0
 public static void InvokeTextTranslation(object sender, TextTranslationEventArgs e)
 {
     TextTranslation?.Invoke(sender, e);
 }
    public override void OnInspectorGUI()
    {
        TextTranslation translation = (TextTranslation)target;

        translation.index = EditorGUILayout.Popup("Label", translation.index, labels);
    }
Exemple #28
0
    public static string ProcXHTML(string html, TextTranslation textTranslation = null)
    {
        XmlDocument doc = new XmlDocument();

        doc.LoadXml(html);
        var     body = doc.GetElementsByTagName("body")[0];
        string  comment = "";
        string  lineTemp = "", rubyTemp = "";
        string  pureText = "";//for translate
        XmlNode p        = body.FirstChild;

        bool        closingElement  = false;
        List <bool> normalTagOutput = new List <bool>();

        while (true)
        {
            bool toNext = false;
            if (closingElement)
            {
                closingElement = false;
                toNext         = true;
                switch (p.Name)
                {
                case "p":
                    comment  += "##" + lineTemp + rubyTemp + "\n" + RemainSigns(lineTemp) + "\n" + "##————————————————\n";
                    lineTemp  = "";
                    rubyTemp  = "";
                    pureText += "\n";
                    break;

                default:
                    bool tagOutput = normalTagOutput[normalTagOutput.Count - 1];
                    normalTagOutput.RemoveAt(normalTagOutput.Count - 1);
                    if (tagOutput)
                    {
                        lineTemp += "</" + p.Name + ">";
                    }
                    break;
                }
            }
            else
            {
                switch (p.NodeType)
                {
                case XmlNodeType.Text:
                    lineTemp += p.Value;
                    pureText += p.Value;
                    break;

                case XmlNodeType.Element:
                    switch (p.Name)
                    {
                    case "ruby":
                        string a = "", b = "";
                        Ruby2Text((XmlElement)p, ref a, ref b);
                        lineTemp += a;
                        pureText += a;
                        rubyTemp += "|" + b;
                        toNext    = true;
                        break;

                    case "p":
                        break;

                    case "img":
                        lineTemp += $"<img src=\"{((XmlElement)p).GetAttribute("src")}\" alt={((XmlElement)p).GetAttribute("alt")}>";
                        break;

                    case "image":
                        lineTemp += $"<image href=\"{((XmlElement)p).GetAttribute("href", "http://www.w3.org/1999/xlink")}\">";
                        break;

                    default:
                    {
                        string classTemp = ((XmlElement)p).GetAttribute("class");
                        bool   tagOutput = true;
                        foreach (string classname in notOutputClassNames)
                        {
                            if (classTemp == classname)
                            {
                                tagOutput = false;
                                break;
                            }
                        }
                        if (p.HasChildNodes)
                        {
                            normalTagOutput.Add(tagOutput);
                        }
                        if (tagOutput)
                        {
                            if (classTemp.Length > 0)
                            {
                                classTemp = " class=" + classTemp;
                            }

                            if (p.HasChildNodes)
                            {
                                lineTemp += "<" + p.Name + classTemp + ">";
                            }
                            else
                            {
                                lineTemp += "<" + p.Name + classTemp + "/>";
                            }
                        }

                        break;
                    }
                    }
                    break;
                }
            }
            //move to next
            if (p.HasChildNodes && !toNext)
            {
                p = p.FirstChild;
            }
            else
            if (p.NextSibling == null)
            {
                p = p.ParentNode;
                closingElement = true;
                if (p == body)
                {
                    break;
                }
            }
            else
            {
                p = p.NextSibling;
            }
        }
        comment += lineTemp;
        if (textTranslation != null)
        {
            if (Util.Trim(pureText).Length != 0)
            {
                string[] commentLines = comment.Split('\n');
                while (pureText[pureText.Length - 1] == '\n')
                {
                    pureText = pureText.Substring(0, pureText.Length - 1);
                }
                string[] pureTextLines = pureText.Split('\n');
                var      s             = textTranslation.Translate(pureTextLines);
                for (int i = 0; i < s.Length; i++)
                {
                    if (s[i] == "")
                    {
                        continue;
                    }
                    commentLines[i * 3 + 1] = s[i];
                }
                comment = string.Join('\n', commentLines);
            }
        }
        return(comment);
    }
Exemple #29
0
        private void print_toolpath_stats(List <Toolpath> toolpaths, List <Polyline> rapids)
        {
            double leadins_len = 0;
            double spirals_len = 0;
            double slices_len  = 0;
            double moves_len   = 0;
            double rapids_len  = 0;

            // collect cut lengths
            foreach (Toolpath path in toolpaths)
            {
                if (path.Leadin != null)
                {
                    leadins_len += path.Leadin.GetPerimeter();
                }

                foreach (Sliced_path_item item in path.Trajectory)
                {
                    double len = item.GetPerimeter();

                    switch (item.Item_type)
                    {
                    case Sliced_path_item_type.SPIRAL:
                        spirals_len += len;
                        break;

                    case Sliced_path_item_type.SLICE:
                        slices_len += len;
                        break;

                    case Sliced_path_item_type.CHORD:
                    case Sliced_path_item_type.SMOOTH_CHORD:
                    case Sliced_path_item_type.GUIDE:
                    case Sliced_path_item_type.SLICE_SHORTCUT:
                        moves_len += len;
                        break;
                    }
                }
            }

            // collect rapids lengths
            foreach (Polyline p in rapids)
            {
                rapids_len += p.GetPerimeter();
            }

            double cut_len = leadins_len + spirals_len + slices_len + moves_len;

            Logger.log(2, TextTranslation.Translate("Toolpath distance '{0}' : {1} + rapids : {2} = total : {3}"),
                       base.Name,
                       cut_len,
                       rapids_len,
                       cut_len + rapids_len);

            // calculate feedrates
            double normal_feedrate = base.CutFeedrate.Cached;

            if (normal_feedrate <= 0)
            {
                return;
            }

            double chord_feedrate  = _chord_feedrate != 0 ? _chord_feedrate : normal_feedrate;
            double spiral_feedrate = _spiral_feedrate != 0 ? _spiral_feedrate : normal_feedrate;
            double leadin_feedrate = _leadin.Cached != null && _leadin.Cached.LeadInFeedrate != 0 ? _leadin.Cached.LeadInFeedrate : normal_feedrate;
            double rapid_feedrate  = 600;   // something big

            double cut_time = 0;

            cut_time += leadins_len / leadin_feedrate;
            cut_time += spirals_len / spiral_feedrate;
            cut_time += slices_len / normal_feedrate;
            cut_time += moves_len / chord_feedrate;

            double rapid_time = rapids_len / rapid_feedrate;

            TimeSpan cut_dur    = new TimeSpan(0, 0, (int)(cut_time * 60.0));
            TimeSpan rapids_dur = new TimeSpan(0, 0, (int)(rapid_time * 60.0));


            Logger.log(2, TextTranslation.Translate("Estimated Toolpath '{0}' duration : {1} + rapids : {2} = total : {3}"),
                       base.Name,
                       cut_dur,
                       rapids_dur,
                       cut_dur + rapids_dur);
        }