/// <summary> /// Selects the specified map location in the <see cref="MapView"/>, replacing either the /// old or the new selection data, depending on the current editing mode.</summary> /// <param name="location"> /// The coordinates of the <see cref="Site"/> to select in the <see cref="MapView"/>. /// </param> /// <param name="center"> /// <c>true</c> to center the <see cref="MapView"/> on the specified <paramref /// name="location"/>; otherwise, <c>false</c>.</param> /// <remarks><para> /// <b>SetSelection</b> always sets the coordinates of the current selection to the /// specified <paramref name="location"/>. /// </para><para> /// In "Modify" mode, or if the previous selection was invalid, <b>SetSelection</b> also /// replaces all other data of the current selection with the data of the specified /// <paramref name="location"/>. The <see cref="Site"/> at that <paramref name="location"/> /// remains unchanged. /// </para><para> /// In "Replace" mode, <b>SetSelection</b> overwrites the data at the specified <paramref /// name="location"/> with that of the current selection, and sets the <see /// cref="SectionTabItem.DataChanged"/> and <see cref="WorldChanged"/> flags. /// </para><para> /// In "Fill" mode, <b>SetSelection</b> also overwrites the data of all contiguous sites /// that contain the same data as the specified <paramref name="location"/>. /// </para><para> /// The specified <paramref name="location"/> may be invalid, in which case the current /// selection is cleared and all site editing controls are reset. <b>SetSelection</b> /// returns <c>false</c> in this case; otherwise, <c>true</c>.</para></remarks> private void SetSelection(PointI location, bool center) { // prevent control input events ++this._ignoreEvents; // highlight site in map panel MapView.SelectedSite = location; // read back to check validity location = MapView.SelectedSite; // clear data if selection invalid if (location == Site.InvalidLocation) { ClearSelection(); goto finished; } // center map view on selection if desired if (center) { MapView.CenterOn(location); } // enable controls for selected site SiteGroup.IsEnabled = true; SiteGroup.Header = Site.FormatLabel(location); // valid selection allows Replace and Fill modes ReplaceToggle.IsEnabled = FillToggle.IsEnabled = true; /* * 1. Modify mode overwrites selection with site * 2. Replace mode overwrites site with selection * 3. Fill mode overwrites area with selection */ if (ModifyToggle.IsChecked == true) { this._selection = this._worldState.CreateArea(location); // show site owner in combo box string owner = this._selection.Owner; if (owner.Length == 0) { OwnerCombo.SelectedIndex = 0; } else { OwnerCombo.SelectedItem = owner; } } else if (this._selection != null && ReplaceToggle.IsChecked == true) { // move selection to new site and replace its data this._selection.Bounds[0] = new RectI(location.X, location.Y, 1, 1); this._worldState.CreateSite(this._selection); // broadcast data changes WorldChanged = true; SectionTab.DataChanged = true; MapView.Redraw(); } else if (this._selection != null && FillToggle.IsChecked == true) { Cursor oldCursor = MainWindow.Instance.Cursor; MainWindow.Instance.Cursor = Cursors.Wait; // check for Area equality with specified location Area area = this._worldState.CreateArea(location); Debug.Assert(area != null); Predicate <PointI> match = (p => area.Equals(this._worldState.CreateArea(p))); // find contiguous sites with equal data FloodFill floodFill = new FloodFill(MapView.MapGrid); if (floodFill.FindMatching(match, location)) { // copy selection data to all sites within fill area foreach (PointI fillSite in floodFill.Nodes) { this._selection.Bounds[0] = new RectI(fillSite.X, fillSite.Y, 1, 1); this._worldState.CreateSite(this._selection); } } // move selection to new site and replace its data this._selection.Bounds[0] = new RectI(location.X, location.Y, 1, 1); this._worldState.CreateSite(this._selection); // broadcast data changes WorldChanged = true; SectionTab.DataChanged = true; MapView.Redraw(); MainWindow.Instance.Cursor = oldCursor; } finished: // allow control input events --this._ignoreEvents; }