/// <summary> /// Tries to retrieve expander control for data grid in search state. /// See <code>ExpandGroup</code> method for details on parameters /// </summary> private Expander GetExpanderForRoot(PowerItem root, CancellationToken token) { if (token.IsCancellationRequested || //thread cancelled _searchView.Groups == null || _searchView.Groups.Count == 0 || //no groups available root == null) //argument exception should be here... { return(null); } var group = _searchView.Groups //get group whose name equals to root's .Cast <CollectionViewGroup>() //Friendly name .FirstOrDefault(g => ((string)g.Name) == root.Root.FriendlyName); if (group == null || (group.ItemCount > 20 && token != CancellationToken.None)) { return(null); //If no such group or it's to large to expand } if (token.IsCancellationRequested) // Just in case { return(null); } return((Expander)dataGrid //get the expander. Method is extension, so no exceptions here, .GetFirstVisualChildOfTypeByContent() //only null may be returned .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent("ScrollContentPresenter") .GetFirstVisualChildOfTypeByContent("ItemsPresenter") .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent(content: group) .GetFirstVisualChildOfTypeByContent()); }
/// <summary> /// Synchronous getter of an icon for PowerItem /// </summary> /// <param name="item">PowerItem we need icon extracted for</param> /// <param name="iconNeeded">type of icon needed - small or large</param> /// <returns>ImageContainer with ImageSources extracted. Can be null.</returns> public static ImageContainer GetImageContainerSync(PowerItem item, API.Shgfi iconNeeded) { Log.Raw("begin>>>>>>>>>>>>>>>", item.FriendlyName); //Checking if there's cached ImageContainer string resolvedArg, descr; try { resolvedArg = PowerItemTree.GetResolvedArgument(item); descr = GetObjectDescriptor(item, resolvedArg); } catch (IOException) { return null; } lock (Cache) { var container = (ImageContainer)(Cache.ContainsKey(descr) ? Cache[descr] : null); Log.Fmt("arg<={0}, descr<={1}, container<={2}", resolvedArg, descr, (container != null ? "not " : "") + "null"); if (container == null) //No cached instance { container = new ImageContainer(resolvedArg, descr, item.SpecialFolderId); Cache.Add(descr, container); if (iconNeeded == API.Shgfi.SMALLICON) container.ExtractSmall(); else container.ExtractLarge(); } #if DEBUG Log.Raw("end<<<<<<<<<<<<<<", item.FriendlyName); #endif return container; } }
/// <summary> /// Switches the state of expander in search view from open to closed and back again /// </summary> /// <param name="root">Can be the <code>PowerItem</code> that lies in search view</param> private void ExpandCollapseGroup(PowerItem root) { var expander = GetExpanderForRoot(root, CancellationToken.None); if (expander != null) //Expander was found? { expander.IsExpanded ^= true; //expand it and set the selection } }
public async void PowerItemSelected(object sender, EventArgs args) { GlobalPowerItem = ((sender as ViewCell).Parent as ListView).SelectedItem as PowerItem; img_PowerItem.Source = GlobalPowerItem.Image; lbl_ItemSelectedName.Text = GlobalPowerItem.Name; await frm_PowerItemSelection.ScaleTo(.1, 250); frm_PowerItemSelection.IsVisible = false; }
public static string ToStringBetter([CanBeNull] this PowerItem pi) { if (pi == null) { return("PowerItem (null)"); } return($"{pi.GetType()} ({pi.PowerItemType}) [{pi.Position}]"); }
private static string GetSuffixForSpecialObject(PowerItem item) { if (item.IsLibrary) { return(Resources.Str_Library); } if (item.SpecialFolderId == API.Csidl.POWER8IMMERSIVE) { return(" (" + item.Argument + ")"); } return(null); }
/// <summary> /// Routine to be performed after some PowerItem's IsPinned property was changed /// </summary> /// <param name="pi">Item whose property has changed</param> private void PinInternal(PowerItem pi) { try { MfuList.PinUnpin(pi); dataGrid.ScrollIntoView(pi); } catch (IndexOutOfRangeException) { Util.DispatchCaughtException(new Exception(Properties.Resources.Err_NoPiExtracted)); } }
/// <summary> /// 修改菜单权限中的值(私有) /// </summary> /// <param name="aobjMenuPower">菜单权限集合</param> /// <param name="aobjPower">一条记录</param> private void SetMenuPower(ref List <PowerItem> aobjMenuPower, PowerItem aobjPower) { if (aobjPower.action != null) { foreach (var item in aobjPower.action) { item.id = -1; item.parentID = aobjPower.id; aobjMenuPower.Add(item); } } }
IEnumerator Pow(PowerItem p) { GameObject cBullet = Bullet; float cDamage = Damage; // Bullet = p.Bullet; Damage = p.Damage; yield return(new WaitForSeconds(p.Time)); Bullet = cBullet; Damage = cDamage; }
/// <summary> /// Searches for the visual group in search results that is represented by /// a PowerItem passed and ensures it's items are displayed. /// </summary> /// <param name="root">The PowerItem that serves as group root for the /// collection generated by one of the search threads. This can be obtained /// by calling Root property of any item that was actually put to the /// collection. Obviously, different search threads search items using /// different search roots which (roots) will then be used as group root /// for search results as well.</param> /// <param name="token">CancellationToken that can cancel the thread.</param> /// <remarks>From the visual tree of MFU list /// searches for the first Expander control /// under the ContentPresenter control /// with Content that ReferenceEquals to the Group in SearchView /// whose (Group's) Name value-equals to the passed root's FriendlyName. /// Cancellation token is checked twice during the execution. /// Expander is searched and expanded only if the number of items /// in related group is 20 or less (performance concideration).</remarks> private void ExpandGroup(PowerItem root, CancellationToken token) { var expander = GetExpanderForRoot(root, token); if (expander != null) //Expander was found? { expander.IsExpanded = true; //expand it and set the selection if (dataGrid.SelectedIndex == -1) { dataGrid.SelectedIndex = 0; //TODO: probably not 0, but idx(first available)? } } }
public void AddPowerItem(int itemId, int level) { int nextLevel = level + 1; PowerItem item = powerItems.Find(x => x.powerId == itemId); if (item != null) { item.powerLevel = nextLevel; } else { powerItems.Add(new PowerItem(itemId, nextLevel)); } }
/// <summary> /// Safely invokes passed item and hides the butonstack - as it is done for the grid /// Used in other code as well, like in the search bar handlers, because they behave /// like invoking something from the grid. /// </summary> /// <param name="item">Grid's selected item (usually)</param> private void InvokeFromDataGrid(PowerItem item) { try { PowerItemTree.SearchTreeCancel(); //if search thread is really slow compared to this UI one, //the following call may execute before search was finished, and MFUList may receive //"process launched" event and update itself, which will cause InvalidOperationException item.Invoke(); } catch (Exception ex) { Util.DispatchCaughtException(ex); } Hide(); }
public void UpdateItemPrefab(PowerItemRow ui_row, Power row) { int currentLevel; PowerItem playerItem = SaveFile.GetInstance().CoreConfig.player.powerItems.Find(x => x.powerId == row.itemId); if (playerItem == null || row.maxLevel == 0) { currentLevel = 1; } else { currentLevel = playerItem.powerLevel; } ui_row.ChangeTitle(row.itemName, currentLevel); ui_row.ChangeIcon(row.GetItemIcon()); ui_row.ChangePrice(row.cost.ToString()); }
private static void SaveTileEntities(string prefabName, Vector3i pos1, Vector3i pos2) { Dictionary <Vector3i, TileEntity> tileEntities = CollectTileEntities(pos1, pos2); var filePath = Path.Combine(Constants.PrefabsFolder, prefabName + TileEntityFileExtension); // Save all tile entities using (var writer = new BinaryWriter(new FileStream(filePath, FileMode.Create))) { writer.Write(TileEntityFileMarker); // [string] constant "7DTD-TE" writer.Write(TileEntityFileVersion); // [Int32] file version number NetworkUtils.Write(writer, pos1); // [Vector3i] original area worldPos1 NetworkUtils.Write(writer, pos2); // [Vector3i] original area worldPos2 // see Assembly-CSharp::Chunk.write() -> search "tileentity.write" writer.Write(tileEntities.Count); // [Int32] number of tile entities foreach (var keyValue in tileEntities) { var posInWorld = keyValue.Key; var tileEntity = keyValue.Value; var posInPrefab = posInWorld - pos1; NetworkUtils.Write(writer, posInPrefab); // [3xInt32] position relative to prefab writer.Write((byte)tileEntity.GetTileEntityType()); // [byte] TileEntityType enum tileEntity.write(writer, TileEntity.StreamModeWrite.Persistency); // [dynamic] tile entity data depending on type Log.Debug($"Wrote tile entity {tileEntity}."); var tileEntityPowered = tileEntity as TileEntityPowered; if (tileEntityPowered != null) { if (!RepairEngine.IsValidTileEntityPowered(tileEntityPowered)) { throw new FriendlyMessageException("The area contains a corrupt power block. Please fix it first with the \"dj-repair\" command."); } var powerItem = tileEntityPowered.GetPowerItem() ?? PowerItem.CreateItem(tileEntityPowered.PowerItemType); SavePowerItem(writer, powerItem); // [dynamic] PowerItem data } } } Log.Out($"Exported {tileEntities.Count} tile entities for prefab {prefabName} from area {pos1} to {pos2}."); }
/// <summary> /// 根据URL 得到相对应的权限 /// </summary> /// <param name="filePath">文件路径</param> /// <param name="path">请求URL</param> /// <param name="objItemPower">返回出去的权限集合</param> /// <returns></returns> private PowerItem GetPowerByPath(string filePath, string path, ref List <PowerItem> objItemPower) { string josnString = File.ReadAllText(filePath + "\\Content\\authority.json", Encoding.Default); JObject jObject = JObject.Parse(josnString); JToken zh = jObject["zh_cn"]; List <PowerItem> pairs = JsonConvert.DeserializeObject <List <PowerItem> >(zh.ToString()); PowerItem powerItem = pairs.Where(t => t.path.Equals(path)).FirstOrDefault(); if (powerItem == null) { return(null); } if (powerItem.action == null) { objItemPower = pairs.Where(t => t.parentID == powerItem.id).ToList(); } else { objItemPower = powerItem.action; } return(powerItem); }
/// <summary> ///结果处理了之后 /// </summary> /// <param name="filterContext">过滤器上下文对象</param> public void OnResultExecuted(ResultExecutedContext filterContext) { string path = filterContext.HttpContext.Request.Url.AbsolutePath; string filePath = filterContext.HttpContext.Server.MapPath("/"); ControllerContext controllerContext = filterContext.Controller.ControllerContext; string viewName = filterContext.Controller.ControllerContext.RouteData.GetRequiredString("action"); HttpSessionStateBase objSesson = filterContext.HttpContext.Session; StringWriter sw = new StringWriter(); List <PowerItem> objItemPower = new List <PowerItem>(); PowerItem objPowerItem = GetPowerByPath(filePath, path, ref objItemPower); if (objPowerItem == null) { return; } string strPower = objPowerItem.text; List <string> keys = GetPowerName(GetDbPower(strPower, objSesson), objItemPower); if (keys == null) { return; } IView view = ViewEngines.Engines.FindPartialView(controllerContext, viewName).View; if (view == null) { return; } ViewContext viewContext = new ViewContext(controllerContext, view, controllerContext.Controller.ViewData, controllerContext.Controller.TempData, sw); viewContext.View.Render(viewContext, sw); StringBuilder st = ExcludeHtml(sw, keys); controllerContext.HttpContext.Response.Clear(); controllerContext.HttpContext.Response.Write(st); }
/// <summary> /// From a container's children selects the one that seems to be discribed by passed parameters /// </summary> /// <param name="argument">Search parameter: child's expected Argument. Case-insensitive.</param> /// <param name="isFolder">Search parameter: child's IsFolder value.</param> /// <param name="container">The PowerItem to search children from.</param> /// <param name="strictFileName">Flag for FS-items to ensure that really desired object will be found.</param> /// <returns></returns> private static PowerItem SearchItemByArgument(string argument, bool isFolder, PowerItem container, bool strictFileName = false) { if(container.AutoExpandIsPending) return null; var endExpr = Path.GetFileName(argument); if (endExpr == null) { endExpr = argument; } else if (strictFileName && !endExpr.StartsWith(@"\")) { endExpr = @"\" + endExpr; } return container.Items.FirstOrDefault(i => i.IsFolder == isFolder && i.Argument.EndsWith(endExpr, StringComparison.InvariantCultureIgnoreCase)); }
/// <summary> /// From the 'source' given, recoursively searches the PowerItem that would Match() the 'query', including /// the 'source' itself, storing results in 'destination'. Finds folders unless they're under Start Menu. /// Cancellable. Intended to be run async. Thread/UI-thread-safe. /// </summary> /// <param name="query">Something searched results should Match() to.</param> /// <param name="source">Tree to search from, including the collection root item passed /// (but not the source.Root itself if the passed item isn't the root of the collection)</param> /// <param name="destination">Collection to store data in</param> /// <param name="stop">Cancellation token from initializer thread</param> private static void SearchItems(string query, PowerItem source, IList<PowerItem> destination, CancellationToken stop) { if(stop.IsCancellationRequested) return; if ((!source.IsFolder || source.Root != StartMenuRootItem) && source.Match(query)) {//return ((folders for not StartMenu children) or files) that Match() the query lock (destination) { if (!stop.IsCancellationRequested && //this item wasn't added before !destination.Any(d => d.FriendlyName == source.FriendlyName && d.IsFolder == source.IsFolder)) Util.Send(() => { if (!stop.IsCancellationRequested) destination.Add(source); }); } } if (!source.AutoExpandIsPending) foreach (var powerItem in source.Items) SearchItems(query, powerItem, destination, stop); }
static void Main() { var win = new RenderWindow( new VideoMode(1200, 600), "키위세개어 게임" ); win.SetFramerateLimit(60); win.KeyPressed += (sender, args) => { if (!start) { start = true; } if (args.Code == Keyboard.Key.X) { if (firepower == 100) { poweritem.Clear(); score += kiwis.Count * 10; kiwis.Clear(); firepower = 0; } return; } else if (args.Code == Keyboard.Key.R) { firepower = 0; score = 0; kiwiposition = new Vector2f(15, 10); kiwidirection = Direction.right; dead = false; kiwis.Clear(); kiwitrails.Clear(); poweritem.Clear(); } switch (args.Code) { case Keyboard.Key.Left: if (kiwidirection == Direction.right) { return; } else { kiwidirection = Direction.left; } break; case Keyboard.Key.Right: if (kiwidirection == Direction.left) { return; } else { kiwidirection = Direction.right; } break; case Keyboard.Key.Up: if (kiwidirection == Direction.down) { return; } else { kiwidirection = Direction.up; } break; case Keyboard.Key.Down: if (kiwidirection == Direction.up) { return; } else { kiwidirection = Direction.down; } break; } }; win.Closed += (sender, args) => { win.Close(); }; // PREPARE GAME SPRITES var FieldBlock = new RectangleShape(new Vector2f(30, 30)) { FillColor = Color.White, OutlineColor = Color.Black, OutlineThickness = 1.0f }; var BorderBlock = new RectangleShape(new Vector2f(30, 30)) { FillColor = Color.Yellow, OutlineColor = Color.Black, OutlineThickness = 1.0f }; var FirePowerStatus = new Text("땔깜게이지", new Font("resources/kpdl.ttf")) { CharacterSize = 26, Position = new Vector2f(930, 30) }; var FirePowerGuage = new RectangleShape(new Vector2f(0, 30)) { FillColor = Color.Red, Position = new Vector2f(930, 70) }; var Score = new Text("점수", new Font("resources/kpdl.ttf")) { CharacterSize = 26, Position = new Vector2f(930, 110) }; var ScoreText = new Text("", new Font("resources/kpdl.ttf")) { CharacterSize = 26, Position = new Vector2f(930, 150) }; var Status = new Text("상태", new Font("resources/kpdl.ttf")) { CharacterSize = 26, Position = new Vector2f(930, 190) }; var StatusText = new Text("정상", new Font("resources/kpdl.ttf")) { CharacterSize = 26, Position = new Vector2f(930, 230) }; var KiwiHeadTexture = new Texture("resources/kiwi_head.png"); var KiwiHead = new Sprite(KiwiHeadTexture); var KiwiTexture = new Texture("resources/kiwi_item.png"); var Kiwi = new Sprite(KiwiTexture); var Start = new Text("Press Anykey to Start", new Font("resources/kpdl.ttf")) { CharacterSize = 50, Color = Color.Red, Position = new Vector2f(30, 30) }; var DeadTexture = new Texture("resources/dead.png"); var Dead = new Sprite(DeadTexture); // RESET GAME PARAMETERS firepower = 0; kiwiposition = new Vector2f(15, 10); kiwidirection = Direction.right; while (win.IsOpen) { win.DispatchEvents(); if (start) { // UPDATE GAME STATE if (gametick >= GAME_TICK && !dead) { for (var k = kiwitrails.Count - 1; k > 0; --k) { kiwitrails[k] = kiwitrails[k - 1]; } if (kiwitrails.Count != 0) { kiwitrails[0] = kiwiposition; } switch (kiwidirection) { case Direction.up: kiwiposition.Y -= 1; break; case Direction.down: kiwiposition.Y += 1; break; case Direction.left: kiwiposition.X -= 1; break; case Direction.right: kiwiposition.X += 1; break; } if (itemtick >= ITEM_TICK && kiwitrails.Count == 3) { // CREATE ITEM ON FIELD bool regen; do { regen = false; float randX, randY; ItemType randItem; var rand = new Random(); randX = rand.Next(1, 28); randY = rand.Next(1, 18); randItem = (ItemType)rand.Next(1, 3); var newitem = new PowerItem(randX, randY, randItem); if (!kiwis.Contains(newitem.position)) { foreach (var item in poweritem) { if (item.position == newitem.position) { regen = true; break; } } if (!regen) { poweritem.Add(newitem); } } else { continue; } } while (regen); itemtick = 0; } if (kiwis.Count == 0 || kiwitick >= KIWI_TICK) { // CREATE KIWI ON FIELD if (kiwitrails.Count == 3 || kiwis.Count == 0) { bool regen; do { regen = false; float randX, randY; var rand = new Random(); randX = rand.Next(1, 28); randY = rand.Next(1, 18); var newkiwi = new Vector2f(randX, randY); if (!kiwis.Contains(newkiwi)) { foreach (var item in poweritem) { if (item.position == newkiwi) { regen = true; break; } } if (!regen) { kiwis.Add(newkiwi); } } } while (regen); } kiwitick = 0; } score++; gametick = 0; } gametick++; itemtick++; kiwitick++; // CHECK COLLISION if (kiwiposition.Y == 0 || kiwiposition.Y == 19 || kiwiposition.X == 0 || kiwiposition.X == 29) { dead = true; } foreach (var kiwi in kiwis.ToArray()) { if (kiwiposition.X == kiwi.X && kiwiposition.Y == kiwi.Y) { if (kiwitrails.Count == 3) { dead = true; } else { score += 50; var newkiwi = new Vector2f(); switch (kiwidirection) { case Direction.up: if (kiwitrails.Count == 0) { newkiwi.X = KiwiHead.Position.X; newkiwi.Y = KiwiHead.Position.Y + 1; } else { newkiwi.X = kiwitrails[kiwitrails.Count - 1].X; newkiwi.Y = kiwitrails[kiwitrails.Count - 1].Y + 1; } break; case Direction.down: if (kiwitrails.Count == 0) { newkiwi.X = KiwiHead.Position.X; newkiwi.Y = KiwiHead.Position.Y - 1; } else { newkiwi.X = kiwitrails[kiwitrails.Count - 1].X; newkiwi.Y = kiwitrails[kiwitrails.Count - 1].Y - 1; } break; case Direction.left: if (kiwitrails.Count == 0) { newkiwi.X = KiwiHead.Position.X + 1; newkiwi.Y = KiwiHead.Position.Y; } else { newkiwi.X = kiwitrails[kiwitrails.Count - 1].X + 1; newkiwi.Y = kiwitrails[kiwitrails.Count - 1].Y; } break; case Direction.right: if (kiwitrails.Count == 0) { newkiwi.X = KiwiHead.Position.X - 1; newkiwi.Y = KiwiHead.Position.Y; } else { newkiwi.X = kiwitrails[kiwitrails.Count - 1].X - 1; newkiwi.Y = kiwitrails[kiwitrails.Count - 1].Y; } break; } kiwitrails.Add(newkiwi); kiwis.Remove(kiwi); break; } } } foreach (var item in poweritem.ToArray()) { if (kiwiposition.X == item.position.X && kiwiposition.Y == item.position.Y) { switch (item.itemtype) { case ItemType.firebase: score += 50; firepower += 20; break; case ItemType.unity: score += 70; firepower += 30; break; case ItemType.vuejs: score += 100; firepower += 50; break; } poweritem.Remove(item); break; } } } if (firepower > 100) { firepower = 100; } if (score >= 1000 && !stp1) { stp1 = true; gametick--; } if (score >= 2500 && !stp2) { stp2 = true; gametick--; } if (score >= 5000 && !stp3) { stp3 = true; gametick--; } // REDRAW GAME SCREEN win.Clear(); for (var x = 0; x < 30; ++x) { for (var y = 0; y < 20; ++y) { Drawable drawrect; if (y == 0 || y == 19 || x == 0 || x == 29) { BorderBlock.Position = new Vector2f(x * 30, y * 30); drawrect = BorderBlock; } else { FieldBlock.Position = new Vector2f(x * 30, y * 30); drawrect = FieldBlock; } win.Draw(drawrect); } } if (start) { // DRAW KIWI KiwiHead.Position = new Vector2f(kiwiposition.X * 30, kiwiposition.Y * 30); win.Draw(KiwiHead); foreach (var kiwi in kiwitrails) { Kiwi.Position = new Vector2f(kiwi.X * 30, kiwi.Y * 30); win.Draw(Kiwi); } } else { win.Draw(Start); } foreach (var kiwipos in kiwis) { Kiwi.Position = new Vector2f(kiwipos.X * 30, kiwipos.Y * 30); win.Draw(Kiwi); } foreach (var item in poweritem) { item.sprite.Position = new Vector2f(item.position.X * 30, item.position.Y * 30); win.Draw(item.sprite); } win.Draw(FirePowerStatus); FirePowerGuage.Size = new Vector2f(firepower * 2.3f, 30); FirePowerGuage.FillColor = firepower == 100 ? Color.Blue : Color.Red; win.Draw(FirePowerGuage); win.Draw(Score); ScoreText.DisplayedString = score.ToString(); win.Draw(ScoreText); win.Draw(Status); if (dead) { StatusText.DisplayedString = "사망"; StatusText.Color = Color.Red; Dead.Position = new Vector2f(kiwiposition.X * 30, kiwiposition.Y * 30); win.Draw(Dead); } else { StatusText.DisplayedString = "정상"; StatusText.Color = Color.Blue; } win.Draw(StatusText); win.Display(); } }
/// <summary> /// Gets a string that represents a kind of tag for icon for PowerItem passed /// </summary> /// <param name="item">PowerItem which we need icon for</param> /// <param name="resolved">Resolved argument for item.</param> private static string GetObjectDescriptor(PowerItem item, string resolved) { if (item.IsFolder || item.IsSpecialObject) return item.NonCachedIcon ? resolved : "*"; var rl = resolved.ToLower(); return rl.EndsWith(".lnk") || rl.EndsWith(".exe") || rl.EndsWith(".cpl") ? resolved : Path.GetExtension(resolved); }
/// <summary> /// Returns string, of a Path kind, that can be passed to a system, and will /// represent the passed PowerItem. Depending on Caller Name, may invoke /// automatic Link resolution for Link PowerItems. "Denamespaces" the /// passed ControlPanel item returning open command for it. /// </summary> /// <param name="item">The PowerItem which has to be located/properties for /// which have to be shown.</param> /// <param name="callerName">String, the name of clicked menu item, hendler /// of which is calling this method. Recognizes "AppOpenTargetContainer" and /// "AppShowTargetProperties".</param> /// <returns>Path to binary FS object that represents the passed PowerItem or /// the target of its link.</returns> private static string Args4PropsAndCont(PowerItem item, string callerName) { string arg = null; if (item.IsControlPanelChildItem) { var executor = Util.GetOpenCommandForClass(item.Argument); if (executor != null && File.Exists(executor.Item1)) arg = executor.Item1; } if (arg == null) arg = PowerItemTree.GetResolvedArgument(item); if (item.IsLink && (callerName == "AppOpenTargetContainer" || callerName == "AppShowTargetProperties")) arg = item.ResolvedLink; return arg; }
public WinSearchEventArgs(PowerItem root, CancellationToken token, bool searchCompleted) { Root = root; Token = token; SearchCompleted = searchCompleted; }
/// <summary> /// Initializes an asynchronous scan of some FS folder /// </summary> /// <param name="item">A PowerItem that represents an FS folder or a Windows Library</param> /// <param name="basePath">If item passed represents folder under Start Menu, place here corresponding /// (Common or User) special folder path. Empty string otherwise. See AddSubItem for details.</param> /// <param name="recoursive">True to scan subdirectories. True by default.</param> public static void ScanFolder(PowerItem item, string basePath, bool recoursive = true) { ThreadPool.QueueUserWorkItem(o => ScanFolderSync(item, basePath, recoursive)); }
/// <summary>Safely converts PowerItem to a string representation of it's final target. /// Functionally equivalent to <code>GetResolvedArgument()</code> except that for links /// it returns actual link target. </summary> /// <param name="item">The PowerItem to convert</param> /// <returns>For Power Items that reference a link, returns link's target. /// See <see cref="GetResolvedArgument"/> for other options.</returns> public static string GetResolvedTarget(PowerItem item) { return item.IsLink ? item.ResolvedLink : GetResolvedArgument(item); }
/// <summary> /// Handles specific key presses when focus is in Data grid: /// - Enter starts the selected PowerItem, if any; /// - Tab/Shift-Tab moves focus to correct controls so that grid doesn't /// hold focus inside. There are arrow buttons for that. /// </summary> private void DataGridPreviewKeyDown(object sender, KeyEventArgs e) { var pi = dataGrid.SelectedItem as PowerItem; switch (e.Key) { case Key.Enter: if (pi != null && !pi.AreItemsDisplayed) { e.Handled = true; InvokeFromDataGrid(pi); } break; case Key.Tab: e.Handled = true; //todo: check why CTRL is tested differently in other places if (pi != null && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) { //CTRL+Tab >> put path to item to search bar var t = "\"" + PowerItemTree.GetResolvedTarget(pi) + "\" "; SearchBox.Text = t; SearchBox.Focus(); SearchBox.CaretIndex = t.Length; } else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) { AllItemsMenuRoot.Focus(); //SHIFT+Tab >> focus backwards } else { SearchBox.Focus(); //Tab >> focus forwards } break; case Key.Up: case Key.Down: if (pi != null && pi.AreItemsDisplayed) { return; //Do not handle keys when JL is in focus } //Not in search view when we press Up/Down if ((System.Windows.Forms.Control.ModifierKeys & Keys.Control) > 0 && dataGrid.ItemsSource.Equals(MfuItems)) { //with CTRL if (dataGrid.SelectedIndex > -1 && SettingsManager.Instance.MfuIsCustom) { //...and we have something selected, and we're in custom MFU... var si = dataGrid.SelectedItem as PowerItem; //...and more than 1 in (un) pinned group if (si != null && MfuItems.Count(m => m.IsPinned == si.IsPinned) > 1) { //=> move item itself e.Handled = true; dataGrid.Focus(); //.Net 4.5 hack. Datagrid in .Net4.5 doesn't switch focus to new row int increment = (e.Key == Key.Up ? -1 : 1); int i = dataGrid.SelectedIndex; PowerItem target = null; do //search for nearest item with same pinning state { i += increment; if (i == -1) { i = MfuItems.Count - 1; } else if (i == MfuItems.Count) { i = 0; } if (MfuItems[i].IsPinned == si.IsPinned) { target = MfuItems[i]; } } while (target == null); MfuList.MoveCustomListItem(si, target); } } } else if ((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == 0) //Not with CTRL, { // regardless of source => just move selection e.Handled = true; var idx = dataGrid.SelectedIndex + (e.Key == Key.Up ? -1 : 1); if (idx < 0) { idx = dataGrid.Items.Count - 1; } if (idx >= dataGrid.Items.Count) { idx = 0; } dataGrid.SelectedIndex = idx; } if (dataGrid.SelectedItem != null) //when in search view and no hits/in clear custom list { dataGrid.ScrollIntoView(dataGrid.SelectedItem); } break; case Key.P: if (pi != null && pi.IsMfuChild) { e.Handled = true; pi.IsPinned ^= true; PinInternal(pi); dataGrid.Focus(); } break; case Key.X: if (pi != null && dataGrid.ItemsSource.Equals(_searchView)) { e.Handled = true; ExpandCollapseGroup(pi); dataGrid.Focus(); } break; case Key.Right: case Key.Left: if (pi != null) { e.Handled = true; pi.AreItemsDisplayed ^= true; } break; } }
/// <summary> /// Synchronously scanns some FS folder, filling Items list of item passed /// </summary> /// <param name="item">A PowerItem that represents an FS folder, special folder or a Windows Library</param> /// <param name="basePath">If item passed represents folder under Start Menu, place here corresponding /// (Common or User) special folder path. Empty string otherwise. See AddSubItem for details.</param> /// <param name="recoursive">True to scan subdirectories.</param> private static void ScanFolderSync(PowerItem item, string basePath, bool recoursive) { //Obtain full fs path to current location var curDir = basePath + (item.Argument ?? Util.ResolveSpecialFolder(item.SpecialFolderId)); try { Log.Raw("In: " + curDir, item.ToString()); //Parse child directories and recoursively call the ScanFolderSync foreach (var directory in item.IsLibrary ? GetLibraryDirectories(curDir) : Directory.GetDirectories(curDir)) {//Skip hidden directories if ((File.GetAttributes(directory).HasFlag(FileAttributes.Hidden))) { Log.Raw("Skipped because item appears to be hidden"); continue; } //Otherwise add the directory item to this PowerItem var subitem = AddSubItem(item, basePath, directory, true, autoExpand: !recoursive); if (recoursive) ScanFolderSync(subitem, basePath, true); } if (item.IsLibrary)//Since Libraries are actually files, but were already parsed as folders, we shan't continue... return; //Proceed with files var resources = new Dictionary<string, string>(); var dsktp = curDir + "\\desktop.ini"; if (File.Exists(dsktp)) //Let's parse Desktop.ini if it exists { using (var reader = new StreamReader(dsktp, System.Text.Encoding.Default, true)) { string str; //TODO: rewrite!!! Currently elements located after LFN section aren't parsed! while ((str = reader.ReadLine()) != null && !str.Contains("[LocalizedFileNames]")) { if (str.StartsWith("IconFile=") || str.StartsWith("IconResource=")) { Util.Post(() => { item.NonCachedIcon = true; item.Icon = null; }); } if (str.StartsWith("LocalizedResourceName=")) { item.ResourceIdString = str.Substring(22); } } while ((str = reader.ReadLine()) != null && str.Contains("=")) { var pair = str.Split(new[] {'='}, 2); resources.Add(pair[0], pair[1]); } } } //Let's scan files now foreach (var file in Directory.GetFiles(curDir)) { if ((File.GetAttributes(file).HasFlag(FileAttributes.Hidden))) continue; //Skip hidden files var fn = Path.GetFileName(file); var fileIsLib = (Path.GetExtension(file) ?? "") .Equals(".library-ms", StringComparison.InvariantCultureIgnoreCase); AddSubItem(item, basePath, file, fileIsLib, fn != null && resources.ContainsKey(fn) ? resources[fn] : null, fileIsLib); } } catch (UnauthorizedAccessException) {Log.Raw("UnauthorizedAccessException");} //Don't care if user is not allowed to access fileor directory or it's contents catch (IOException) {Log.Raw("IOException");} //Don't care as well if file was deleted on-the-fly, watcher will notify list catch (ArgumentException) {Log.Raw("ArgumentException");} //This usually happens to removable drives finally { //Explicitly set marker showing that enumeration operations may occur on Items from this moment item.AutoExpandIsPending = false; } }
private static void SavePowerItem(BinaryWriter writer, [NotNull] PowerItem powerItem) { // Doing everything here that the PowerItem classes do in write(..) methods, but only for itself, not parents or childs. // Intentionally not using ELSE because of PowerItem inheritence, see: https://abload.de/img/poweritem-hierarchyzvumv.png if (powerItem is PowerItem) { // ReSharper disable once RedundantCast var pi = (PowerItem)powerItem; // None of this is needed for import //writer.Write(pi.BlockID); //NetworkUtils.Write(writer, pi.Position); writer.Write(pi.Parent != null); if (pi.Parent != null) { NetworkUtils.Write(writer, pi.Parent.Position); } //writer.Write((byte)pi.Children.Count); //for (int index = 0; index < pi.Children.Count; ++index) //{ // writer.Write((byte)pi.Children[index].PowerItemType); // pi.Children[index].write(writer); //} } if (powerItem is PowerConsumer) { // nothing to write } if (powerItem is PowerConsumerToggle) { var pi = (PowerConsumerToggle)powerItem; writer.Write(pi.GetIsToggled()); } if (powerItem is PowerElectricWireRelay) { // nothing to write } if (powerItem is PowerRangedTrap) { var pi = (PowerRangedTrap)powerItem; writer.Write(pi.GetIsLocked()); GameUtils.WriteItemStack(writer, pi.Stacks); writer.Write((int)pi.TargetType); } if (powerItem is PowerTrigger) { var pi = (PowerTrigger)powerItem; writer.Write((byte)pi.TriggerType); // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (pi.TriggerType == PowerTrigger.TriggerTypes.Switch) { writer.Write(pi.GetIsTriggered()); } else { writer.Write(pi.GetIsActive()); } if (pi.TriggerType != PowerTrigger.TriggerTypes.Switch) { writer.Write((byte)pi.TriggerPowerDelay); writer.Write((byte)pi.TriggerPowerDuration); writer.Write(pi.GetDelayStartTime()); writer.Write(pi.GetPowerTime()); } if (pi.TriggerType != PowerTrigger.TriggerTypes.Motion) { return; } writer.Write((int)pi.TargetType); } if (powerItem is PowerPressurePlate) { // nothing to write } if (powerItem is PowerTimerRelay) { var pi = (PowerTimerRelay)powerItem; writer.Write(pi.StartTime); writer.Write(pi.EndTime); } if (powerItem is PowerTripWireRelay) { // nothing to write } if (powerItem is PowerConsumerSingle) { // nothing to write } if (powerItem is PowerSource) { var pi = (PowerSource)powerItem; writer.Write(pi.CurrentPower); writer.Write(pi.IsOn); GameUtils.WriteItemStack(writer, pi.Stacks); } if (powerItem is PowerBatteryBank) { // nothing to write } if (powerItem is PowerGenerator) { var pi = (PowerGenerator)powerItem; writer.Write(pi.CurrentFuel); } if (powerItem is PowerSolarPanel) { // nothing to write } Log.Debug($"Exported power item {powerItem.ToStringBetter()}."); }
//Proxy for SearchStartMenuSyncFast. Code literally copypasted from SearchItems and simplified. //Not thread-safe. private static void SearchRootFastSync(string query, PowerItem source, ICollection<PowerItem> destination) { if (!source.IsFolder && source.Match(query) && destination.All(d => d.FriendlyName != source.FriendlyName)) destination.Add(source); if (!source.AutoExpandIsPending) foreach (var powerItem in source.Items) SearchRootFastSync(query, powerItem, destination); }
/// <summary> /// Searches for the visual group in search results that is represented by /// a PowerItem passed and ensures it's items are displayed. /// </summary> /// <param name="root">The PowerItem that serves as group root for the /// collection generated by one of the search threads. This can be obtained /// by calling Root property of any item that was actually put to the /// collection. Obviously, different search threads search items using /// different search roots which (roots) will then be used as group root /// for search results as well.</param> /// <param name="token">CancellationToken that can cancel the thread.</param> /// <remarks>From the visual tree of MFU list /// searches for the first Expander control /// under the ContentPresenter control /// with Content that ReferenceEquals to the Group in SearchView /// whose (Group's) Name value-equals to the passed root's FriendlyName. /// Cancellation token is checked twice during the execution. /// Expander is searched and expanded only if the number of items /// in related group is 20 or less (performance concideration).</remarks> private void ExpandGroup(PowerItem root, CancellationToken token) { var expander = GetExpanderForRoot(root, token); if (expander != null) //Expander was found? { expander.IsExpanded = true; //expand it and set the selection if (dataGrid.SelectedIndex == -1) dataGrid.SelectedIndex = 0; //TODO: probably not 0, but idx(first available)? } }
/// <summary> /// Queries Windows Search service indexer for the items that will mathc the query. Sorts results by search rank. /// Cancellable. Intended to be run from background thread. UI-thread-safe. /// </summary> /// <param name="query">Something the results should match to.</param> /// <param name="ext">When you want to filter only specific types of files, set this to file extension /// (like "wmv"). Set to null otherwise.</param> /// <param name="destination">The collection to store results in.</param> /// <param name="stop">Cancellation token to break the execution.</param> private static void SearchWindows(string query, string ext, IList<PowerItem> destination, CancellationToken stop) { if(stop.IsCancellationRequested) return; const string connText = "Provider=Search.CollatorDSO;Extended Properties='Application=Windows'"; //See MSDN 4 details var comText = @"SELECT TOP 100 System.ItemUrl FROM SYSTEMINDEX WHERE System.Search.Store='FILE' and " + (ext == null ? string.Empty : "System.FileName like '%." + ext + "' and ") + "(FREETEXT ('" + query + "') OR System.FileName like '%" + query + "%') " + "ORDER BY RANK DESC"; //I.e., get 100 files represented by their File:/// -style URI, probably of a given type, //and looking similar to query or matched to it by full-text indexer, ordered by system rank Thread.Sleep(666); //let's give user the possibility to enter something more... OleDbDataReader rdr = null; OleDbConnection connection = null; PowerItem groupItem = null; //needed for visual representation try { if(!stop.IsCancellationRequested) {//Begin search andnotify subscribers connection = new OleDbConnection(connText); connection.Open(); var command = new OleDbCommand(comText, connection) {CommandTimeout = 0}; var h = WinSearchThreadStarted; if (h != null) h(null, new WinSearchEventArgs(null, stop, false)); if(!stop.IsCancellationRequested) rdr = command.ExecuteReader(); } if (rdr != null) { //Build children list groupItem = new PowerItem {FriendlyName = Resources.Str_WindowsSearchResults}; var added = 0; var bs = Path.DirectorySeparatorChar; while (!stop.IsCancellationRequested && added < 50 && rdr.Read()) { lock (destination) { var data = rdr[0].ToString() .Substring(5) .TrimStart(new[] { '/' }) .Replace('/', bs); //uri => path if (data.Length > 1 && data[1] != ':') //UNC? data = bs + bs + data; var source = new PowerItem { Argument = data, Parent = groupItem, IsFolder = Directory.Exists(data) }; if (!destination.Contains(source)) { //switch to UI context Util.Send(() => { if (!stop.IsCancellationRequested) destination.Add(source); }); added++; } } } } } catch (Exception e) { Log.Raw(e.ToString()); } finally { if(rdr != null) rdr.Close(); if(connection != null && connection.State == ConnectionState.Open) connection.Close(); } //Notify subscribers the search is conmpleted if (!stop.IsCancellationRequested) { var h = WinSearchThreadCompleted; if (h != null) h(null, new WinSearchEventArgs(groupItem, stop, true)); } }
/// <summary> /// Tries to retrieve expander control for data grid in search state. /// See <code>ExpandGroup</code> method for details on parameters /// </summary> private Expander GetExpanderForRoot(PowerItem root, CancellationToken token) { if (token.IsCancellationRequested //thread cancelled || _searchView.Groups == null || _searchView.Groups.Count == 0 //no groups available || root == null) //argument exception should be here... return null; var group = _searchView.Groups //get group whose name equals to root's .Cast<CollectionViewGroup>() //Friendly name .FirstOrDefault(g => ((string)g.Name) == root.Root.FriendlyName); if (group == null || (group.ItemCount > 20 && token != CancellationToken.None)) return null; //If no such group or it's to large to expand if (token.IsCancellationRequested) // Just in case return null; return (Expander)dataGrid //get the expander. Method is extension, so no exceptions here, .GetFirstVisualChildOfTypeByContent() //only null may be returned .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent("ScrollContentPresenter") .GetFirstVisualChildOfTypeByContent("ItemsPresenter") .GetFirstVisualChildOfTypeByContent() .GetFirstVisualChildOfTypeByContent(content: group) .GetFirstVisualChildOfTypeByContent(); }
/// <summary>Safely converts PowerItem to a string representation of it's target</summary> /// <param name="item">The PowerItem to convert</param> /// <returns>Something that actually will be opened: /// - Argument for SpecialObjects /// - Runnable parent for P8 JL implementation /// - Folder path for folder-pointing items /// - Full-path argumet for file-pointing items</returns> public static string GetResolvedArgument(PowerItem item) { if(item.IsSpecialObject) return item.Argument; if (item.SpecialFolderId == API.Csidl.POWER8JLITEM) return GetResolvedArgument(item.Parent); var psi = ResolveItem(item); return item.IsFolder ? psi.Arguments : psi.FileName; }
/// <summary> /// Starts asynchronous extraction of ImageContainer for PowerItem /// </summary> /// <param name="item">PowerItem we need icon extracted for</param> /// <param name="iconNeeded">type of icon needed - small or large</param> /// <returns>Always null</returns> public static ImageContainer GetImageContainer(PowerItem item, API.Shgfi iconNeeded) { ImageQueue.Enqueue(new Tuple<PowerItem, API.Shgfi>(item, iconNeeded)); return null; }
/// <summary>Converts PowerItem passed into runnable ProcessStartInfo structure.</summary> /// <param name="item">The PowerItem that needs to be started.</param> /// <param name="prioritizeCommons">For StartMenu items, use this to indicate that /// the common item is desired to be runned in case both are available.</param> /// <returns>ProcessStartInfo structure which can be used to "launch" passed PowerItem. /// This includes but is not limited to: /// - execute program 'item' points to; /// - execute program associated with format of the file 'item' points to; /// - open folder 'item' points to; /// - execute ControlPanel item, the 'item' points to /// ...and so on.</returns> public static ProcessStartInfo ResolveItem(PowerItem item, bool prioritizeCommons = false) { var psi = new ProcessStartInfo(); var arg1 = item.Argument; if (item.IsSpecialObject || arg1 == null) //CPL item or some ::Special//::Folder { bool cplSucceeded = false; if (item.IsControlPanelChildItem) { //Control panel flow item var command = Util.GetOpenCommandForClass(arg1); if (command != null) { psi.FileName = command.Item1; psi.Arguments = command.Item2; cplSucceeded = true; } else {//Sysname-registered CPL items var sysname = Util.GetCplAppletSysNameForClass(arg1); if (!string.IsNullOrEmpty(sysname)) { psi.FileName = "control.exe"; psi.Arguments = "/name " + sysname; cplSucceeded = true; } } } if (!cplSucceeded) //Special folder? { psi.FileName = "explorer.exe"; psi.Arguments = "/N," + (item.Argument ?? Util.ResolveSpecialFolder(item.SpecialFolderId)); } } else if (item.SpecialFolderId == API.Csidl.POWER8JLITEM) {//P8 internal-implementation jump list's command psi = ResolveItem(item.Parent, prioritizeCommons); psi.Arguments = item.Argument; //simply invoke parent with command equal to 'item''s Argument } else //File or folder probably { if (!(arg1.StartsWith("\\\\") || (arg1.Length > 1 && arg1[1] == ':'))) arg1 = PathRoot + item.Argument; //form full path, depending on what Argument is var arg2 = PathCommonRoot + item.Argument; //arg2 ALWAYS starts with common path if (prioritizeCommons) //so, if you set prioritizeCommons, you GUARANTEE it's StartMenu item under Common one arg2 = Interlocked.Exchange(ref arg1, arg2); if (item.IsFolder) {//if folder exists, or it's network path, or the secondary path exists - open in explorer, otherwise fail psi.FileName = "explorer.exe"; if (arg1.StartsWith("\\\\") || Directory.Exists(arg1)) psi.Arguments = arg1; else { if (Directory.Exists(arg2)) psi.Arguments = arg2; else throw new IOException(Resources.Err_GotNoFolder + item.Argument); } } else // if file exists, or secondary evaluated file exists - run, otherwise fail { if (File.Exists(arg1)) psi.FileName = arg1; else { if (File.Exists(arg2)) psi.FileName = arg2; else throw new IOException(Resources.Err_GotNoFile + item.Argument); } } } return psi; }
/// <summary> /// Switches the state of expander in search view from open to closed and back again /// </summary> /// <param name="root">Can be the <code>PowerItem</code> that lies in search view</param> private void ExpandCollapseGroup(PowerItem root) { var expander = GetExpanderForRoot(root, CancellationToken.None); if (expander != null) //Expander was found? expander.IsExpanded ^= true; //expand it and set the selection }
/// <summary> /// For the given parent PowerItem, searches child for given parameters, or creates a new one /// if search is unsuccessful or cannot be executed, and returns the child obtained. /// Thread-safe, UI-thread-safe. /// </summary> /// <param name="item">parent PowerItem, typically a filesystem folder, a Library or a special folder</param> /// <param name="basePath">if 'item' represents a folder under Start menu (and so has relative Argument), /// pass here a full-qualified path to a User or Common Start Menu (the one under which a folder is /// actually located). Use PathRoot and PathCommonRoot fields to simpolify the task. Empty string otherwise.</param> /// <param name="fsObject">Non-virtual non-junction file system object (file or folder), not null, not empty /// (this is the most meaningful parameter). If you need to add a virtual item (e.g. Computer element), use /// direct access to proprties (parent.Items.Add(child); child.Parent=parent;) with respect to /// IsAutoExpandPending property. Child search parameter.</param> /// <param name="isFolder">Sets child's IsFolder property to a value passed. Child search parameter.</param> /// <param name="resourceId">Localized resource identifier in a standard "[@]Library,-resId[__varData*]" form. /// Null by default. Since 0.4 can be set to a required string directly, but in this case it is recommended to /// set FriendlyName explicitly</param> /// <param name="autoExpand">True to mark the item as deferred-expandable. This means it's children won't be enumerated /// synchronously and will be loaded automatically later, when requested by the user. False by default.</param> private static PowerItem AddSubItem(PowerItem item, string basePath, string fsObject, bool isFolder, string resourceId = null, bool autoExpand = false) { var argStr = fsObject.Substring(basePath.Length); //Expected relative argument in case of Start Menu item Log.Raw("In: " + fsObject, item.ToString()); var child = autoExpand || item.AutoExpandIsPending //Searching... ? null : item.Items.FirstOrDefault(i => string.Equals(i.Argument, argStr, StringComparison.CurrentCultureIgnoreCase) && i.IsFolder == isFolder); Log.Raw("child: " + (child == null ? "null" : child.ToString()), item.ToString()); if(child == null) //Generating... { child = new PowerItem { Argument = argStr, Parent = item, IsFolder = isFolder, ResourceIdString = resourceId, AutoExpand = autoExpand }; Util.Send(() => item.Items.Add(child)); //Synchronously add item in UI thread } return child; }
public static void SetHasChangesLocal(this PowerItem obj, bool value) { fi_PowerItem_hasChangesLocal.SetValue(obj, value); }
/// <summary> /// From collection tree passed, searches for a parent item (i.e. container) of the one that would /// represent the object described by passed tuple. Optionally tries to generate items in the middle. /// </summary> /// <param name="baseAndArg">Tuple returned by <code>PathToBaseAndArg</code></param> /// <param name="collectionRoot">The root of collection, like <code>StartMenuRootItem</code></param> /// <param name="autoGenerateSubItems">Should method generate proxy Folder items in between of last available /// and required items?</param> private static PowerItem SearchContainerByArgument(Tuple<string, string> baseAndArg, PowerItem collectionRoot, bool autoGenerateSubItems) { if (!string.IsNullOrEmpty(collectionRoot.Argument) && baseAndArg.Item2.StartsWith(collectionRoot.Argument, StringComparison.InvariantCultureIgnoreCase) && baseAndArg.Item2 != collectionRoot.Argument) {//Make argument relative to Root baseAndArg = new Tuple<string, string>(baseAndArg.Item1, baseAndArg.Item2.Substring(collectionRoot.Argument.Length + 1)); } var sourceSplitted = baseAndArg.Item2.Split(new[] {'\\'}, StringSplitOptions.RemoveEmptyEntries); if (sourceSplitted.Length > 0 && sourceSplitted[0].EndsWith(":")) sourceSplitted[0] += "\\"; //For MyComputer children var item = collectionRoot; for (int i = 0; i < sourceSplitted.Length - 1; i++) { var prevItem = item; item = item.AutoExpandIsPending ? null : item.Items.FirstOrDefault(j => j.IsFolder && j.Argument.EndsWith(sourceSplitted[i], StringComparison.InvariantCultureIgnoreCase)); if (item == null && autoGenerateSubItems && !string.IsNullOrEmpty(baseAndArg.Item1)) { item = AddSubItem(prevItem, baseAndArg.Item1, baseAndArg.Item1 + prevItem.Argument + "\\" + sourceSplitted[i], true); } else if (item == null) { break; } } return item; }
private static void LoadPowerItem(BinaryReader _br, [NotNull] PowerItem powerItem, Vector3i posDelta) { // Doing everything here that the PowerItem classes do in read(..) methods, but only for itself, not parents or childs. // Intentionally not using ELSE to because of PowerItem inheritence, see: https://abload.de/img/poweritem-hierarchyzvumv.png if (powerItem is PowerItem) // always { // ReSharper disable once RedundantCast var pi = (PowerItem)powerItem; // No need to set block data; it's already set from tile import //this.BlockID = _br.ReadUInt16(); //this.SetValuesFromBlock(); //this.Position = NetworkUtils.ReadVector3i(_br); if (_br.ReadBoolean()) // has parent { // Do NOT use this, because it removes the connection from powerItems previous power item, which belongs to the old prefab location //PowerManager.Instance.SetParent(this, PowerManager.Instance.GetPowerItemByWorldPos(NetworkUtils.ReadVector3i(_br))); var parentPos = NetworkUtils.ReadVector3i(_br); parentPos += posDelta; // Adjusting to new position pi.Parent = PowerManager.Instance.GetPowerItemByWorldPos(parentPos); if (pi.Parent != null) // Could happen when parent was not included in prefab area { // Add reciprocal connection back from parent if (!pi.Parent.Children.Contains(pi)) { pi.Parent.Children.Add(pi); } // When power item receives a parent, it is not a root power item anymore and must be removed from the list var rootPowerItems = PowerManager.Instance.GetRootPowerItems(); if (rootPowerItems.Contains(pi)) { rootPowerItems.Remove(pi); } } } pi.SendHasLocalChangesToRoot(); // No need to read in children; the needed ones are added by tile import //int num = (int)_br.ReadByte(); //this.Children.Clear(); //for (int index = 0; index < num; ++index) //{ // PowerItem node = PowerItem.CreateItem((PowerItem.PowerItemTypes)_br.ReadByte()); // node.read(_br, _version); // PowerManager.Instance.AddPowerNode(node, this); //} } if (powerItem is PowerConsumer) { // nothing to read } if (powerItem is PowerConsumerToggle) { var pi = (PowerConsumerToggle)powerItem; pi.SetIsToggled(_br.ReadBoolean()); } if (powerItem is PowerElectricWireRelay) { // nothing to read } if (powerItem is PowerRangedTrap) { var pi = (PowerRangedTrap)powerItem; pi.SetIsLocked(_br.ReadBoolean()); pi.SetSlots(GameUtils.ReadItemStack(_br)); pi.TargetType = (PowerRangedTrap.TargetTypes)_br.ReadInt32(); } if (powerItem is PowerTrigger) { var pi = (PowerTrigger)powerItem; pi.TriggerType = (PowerTrigger.TriggerTypes)_br.ReadByte(); if (pi.TriggerType == PowerTrigger.TriggerTypes.Switch) { pi.SetIsTriggered(_br.ReadBoolean()); } else { pi.SetIsActive(_br.ReadBoolean()); } if (pi.TriggerType != PowerTrigger.TriggerTypes.Switch) { pi.TriggerPowerDelay = (PowerTrigger.TriggerPowerDelayTypes)_br.ReadByte(); pi.TriggerPowerDuration = (PowerTrigger.TriggerPowerDurationTypes)_br.ReadByte(); pi.SetDelayStartTime(_br.ReadSingle()); pi.SetPowerTime(_br.ReadSingle()); } if (pi.TriggerType != PowerTrigger.TriggerTypes.Motion) { return; } pi.TargetType = (PowerTrigger.TargetTypes)_br.ReadInt32(); } if (powerItem is PowerPressurePlate) { // nothing to read } if (powerItem is PowerTimerRelay) { var pi = (PowerTimerRelay)powerItem; pi.StartTime = _br.ReadByte(); pi.EndTime = _br.ReadByte(); } if (powerItem is PowerTripWireRelay) { // nothing to read } if (powerItem is PowerConsumerSingle) { // nothing to read } if (powerItem is PowerSource) { var pi = (PowerSource)powerItem; pi.LastCurrentPower = pi.CurrentPower = _br.ReadUInt16(); pi.IsOn = _br.ReadBoolean(); pi.SetSlots(GameUtils.ReadItemStack(_br)); pi.SetHasChangesLocal(true); } if (powerItem is PowerBatteryBank) { // nothing to read } if (powerItem is PowerGenerator) { var pi = (PowerGenerator)powerItem; pi.CurrentFuel = _br.ReadUInt16(); } if (powerItem is PowerSolarPanel) { // nothing to read } Log.Debug($"Loaded power item {powerItem.ToStringBetter()}."); }