Removing Slide Layouts from Presentation - c#

I have a following code for removing slide layout parts:
var presentation = output.PresentationPart;
var usedSlideLayouts = presentation.SlideParts.Select(it => it.SlideLayoutPart).ToList();
foreach (var sm in presentation.SlideMasterParts)
{
var slideLayoutIds = sm.SlideMaster.SlideLayoutIdList.Elements<SlideLayoutId>().ToList();
var slideLayoutParts = sm.SlideLayoutParts.ToList();
var i = 0;
foreach (var slp in slideLayoutParts)
{
var isUsed = usedSlideLayouts.Any(usl => usl == slp);
if (!isUsed)
{
var slideLayoutId = slideLayoutIds[i];
slideLayoutId.Remove();
sm.DeletePart(slp);
}
i++;
}
}
When i save the presentation after running it my presentation is corrupted (needs to be restored before opening in power point).
From what I saw (by unzipping the pptx) this could be because of the fact that there is only one slide layout but it's internal URI is like 'slideLayout2.xml'. Is there a way to refresh that internal URI?
For anyone wondering I attached a powerpoint in this github issue:
https://github.com/OfficeDev/Open-XML-SDK/issues/218

Your slideLayoutId is the wrong one. The SlideLayoutParts are not necessarily returned in the same order as the SlideLayoutIds.
You can solve this by changing the line
var slideLayoutId = slideLayoutIds[i];
to
var slideLayoutId = slideLayoutIds.Where(sid => sid.RelationshipId == sm.GetIdOfPart(slp)).FirstOrDefault();
This picks the correct slideLayoutId based on the RelationshipId.

Related

How to vertically format embedded fields

Current Formatting For Embed Fields
Here is an embed I currently use for my semi-public Ark Servers.
First field is the Map name,
Second field is the direct connect IP Address,
Third field is if/where there is a community base on that map.
As you can see it works as intended but if there's to much info on a single line in the field the formatting is screwed up. Is there a way to fix this?
I'm using 3 separate stream builders to build the different fields and then adding them to the embed. If code is needed I can post a "dumbed down version" so it doesn't take up the whole page.
var linkHeading = "steam://connect/";
var sb = new StringBuilder();
var sb2 = new StringBuilder();
var sb3 = new StringBuilder();
var embed = new EmbedBuilder();
embed.WithColor(new Color(0, 255, 0));
embed.Title = "List of Server Ips";
JObject o1;
using (StreamReader file = File.OpenText("serverips.json"))
using (JsonTextReader reader = new JsonTextReader(file))
{
o1 = (JObject)JToken.ReadFrom(reader);
}
var ipsObject = JsonConvert.DeserializeObject<Rootobject>(o1.ToString());
sb.AppendLine("The Island: ");
sb2.AppendLine($"{linkHeading}{ipsObject.TheIsland.ip}:{ipsObject.TheIsland.port}/");
if(ipsObject.TheIsland.comm != "")
{
sb3.AppendLine($"Comm: {ipsObject.TheIsland.comm}");
} else { sb3.AppendLine($"No Comm Info Available"); };
sb.AppendLine("Aberration: ");
sb2.AppendLine($"{linkHeading}{ipsObject.Aberration.ip}:{ipsObject.Aberration.port}/");
if (ipsObject.Aberration.comm != "")
{
sb3.AppendLine($"Comm: {ipsObject.Aberration.comm}");
} else { sb3.AppendLine($"No Comm Info Available"); };
embed.WithDescription($"Cluster Ip and Comm Information");
embed.AddField(x =>
{
x.Name = "Map";
x.Value = sb.ToString();
x.IsInline = true;
});
embed.AddField(x =>
{
x.Name = "IP";
x.Value = sb2.ToString();
x.IsInline = true;
});
embed.AddField(x =>
{
x.Name = "Comm?";
x.Value = sb3.ToString();
x.IsInline = true;
});
await Context.User.SendMessageAsync(null, false, embed.Build());
await ReplyAsync("Server Ip List was sent directly to your inbox! :)");
You don't have that much control over how embed fields are displayed. The only thing you control in regards to fields are if they inline or not. The rendering is completely up to Discord and the end users screen size. For example, your current output on mobile will ignore the inline setting and list the fields one on top of the other instead of side by side.
Unless your fields consistently contain a small amount of text each you can't guarantee how the end use will see the output. If you need to guarantee some sort of consistent structured display across all devices, your best bet is to use an image.

UWP MapControl highlight countries

I’m writing a little app which will receive a country code (2 ISO letters) and a state code (also 2 letters ISO code).
I would like to highlight (And color) the region specified by these 2 information (So let’s say “CA, QC”, will highlight Quebec state in Canada)
I don’t need Anything else (Well, maybe FadeIn, FadeOut animation, but I’ll figure this one out later)
All zoom/tap/click/other actions are blocked.
The MapControl declaration is really easy :
<maps:MapControl Grid.Row="1" x:Name="myMap" ZoomLevel="0"/>
Thanks in advance
Edit: After a lot of research, the help from following answer, I’m astonished that a BASIC action is NOT a part of Microsoft’s platform. That’s insane. All back end was coded in less than 30 minutes (Including authentication, listing properties, checking access level, setting up SignalR callbacks), but on the visual side, welp, we have NOTHING from UWP platform. That’s just sad.
/bye UWP, I’ve tried. multiple times.
Edit 2 : Made it work with some adjustements :
if (feature != null && (feature.Geometry.Type == GeoJSONObjectType.Polygon) || (feature.Geometry.Type == GeoJSONObjectType.MultiPolygon))
{
myMap.MapElements.Clear();
MapPolygon polygon = null;
if (feature.Geometry.Type == GeoJSONObjectType.Polygon)
{
var polygonGeometry = feature.Geometry as Polygon;
polygon = new MapPolygon
{
Path = new Geopath(polygonGeometry.Coordinates[0].Coordinates.Select(coord => new BasicGeoposition() { Latitude = coord.Latitude, Longitude = coord.Longitude })),
FillColor = Colors.DarkRed
};
myMap.MapElements.Add(polygon);
}
else
{
var ploy = (feature.Geometry as MultiPolygon);
foreach (var item in ploy.Coordinates)
{
var polygon1 = new MapPolygon
{
Path = new Geopath(item.Coordinates[0].Coordinates.Select(coord => new BasicGeoposition() { Latitude = coord.Latitude, Longitude = coord.Longitude })),
FillColor = Colors.DarkRed
};
myMap.MapElements.Add(polygon1);
}
}
}
There is no built-in way to achieve this, so you will have to do some additional steps to make this work.
First you need to download a geojson-based dataset with polygonial definitions of all countries. One lightweight and functional can be found here on GitHub.
Now you need to install the GeoJSON.NET package from NuGet into your project and include the downloaded .geojson file in your project, for example in the Assets folder. Make sure that its Build action is set to Content.
Now you can use code like this to highlight a country by creating a MapPolygon and placing it on the map:
private FeatureCollection _countryPolygons = null;
private async void HighlightClick(string country)
{
if (_countryPolygons == null)
{
_countryPolygons = JsonConvert.DeserializeObject<FeatureCollection>(
await FileIO.ReadTextAsync(
await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/countries.geojson",
UriKind.Absolute))));
}
var feature = _countryPolygons.Features.FirstOrDefault(f =>
f.Id.Equals(country, StringComparison.CurrentCultureIgnoreCase));
if (feature != null && feature.Geometry.Type == GeoJSONObjectType.Polygon)
{
var polygonGeometry = feature.Geometry as Polygon;
MapPolygon polygon = new MapPolygon();
polygon.Path = new Geopath(polygonGeometry.Coordinates[0].Coordinates.Select(coord => new BasicGeoposition() { Latitude = coord.Latitude, Longitude = coord.Longitude }));
polygon.FillColor = Colors.DeepSkyBlue;
Map.MapElements.Clear();
Map.MapElements.Add(polygon);
}
}

How to get media devices information?

I'm using the MediaDevices NuGet package to identify all the media devices connected to the computer. I'm not sure how do i get MediaStorageInfo, like how much space it can hold or how many space is available.
The snippet of my code:
var mediadevices = mediadevice.GetDevices();
MediaStorageInfo info = new MediaStorageInfo();
foreach (var device in mediadevices)
{
ulong cap = info.Capacity
ulong freespace = info.FreespaceInObjects;
}
The manual suggested:
var devicess = MediaDevice.GetDevices();
using (var device = devicess.First(d => d.FriendlyName == "My Cell Phone"))
{
device.Connect();
// get list of available storages (SD-Card, Internal Flash, ...)
var objects = device.FunctionalObjects(FunctionalCategory.Storage);
MediaStorageInfo infoss = GetStorageInfo(objects.First());
ulong size = infoss.FreeSpaceInBytes;
device.Disconnect();
}
the GetStorageInfo seems to be missing as the error stated that can't be resolved and doesn't exist in the current contact.I'm not sure how do i pass my MediaDevice into MediaStorageInfo. Any suggestion helps. Thank you!
Just change:
GetStorageInfo(objects.First());
to
device.GetStorageInfo(objects.First())
Than it should look like this:
var devicess = MediaDevice.GetDevices();
using (var device = devicess.First(d => d.FriendlyName == "My Cell Phone"))
{
device.Connect();
// get list of available storages (SD-Card, Internal Flash, ...)
var objects = device.FunctionalObjects(FunctionalCategory.Storage);
MediaStorageInfo infoss = device.GetStorageInfo(objects.First());
ulong size = infoss.FreeSpaceInBytes;
device.Disconnect();
}

How do I get all the entities on a specific layer in a .DWG file without opening the file (C#.NET/AutoCAD)?

I am writing a C#.NET program that interacts with AutoCAD through the AutoCAD .NET API. The program loops through DWG files in a directory and checks every text entity on the "testLayer" layer to see if it matches "testText". I got this to work by opening up every file and making a Selectionfilter to get all of the entities on the "testLayer" layer.
Application.DocumentManager.Open(curfile.FullName, false);
....
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction acTrans = doc.TransactionManager.StartTransaction())
{
ObjectIdCollection ents = new ObjectIdCollection();
// Set up filter and filter on layer name
TypedValue[] tvs = new TypedValue[1] { new TypedValue((int)DxfCode.LayerName, "testLayer")};
SelectionFilter sf = new SelectionFilter(tvs);
PromptSelectionResult psr = ed.SelectAll(sf);
if (psr.Status == PromptStatus.OK)
{
// Get the object ids for all of the entities for the filtered layer
ents = new ObjectIdCollection(psr.Value.GetObjectIds());
foreach (ObjectId objid in ents)
{
DBText dbText = acTrans.GetObject(objid, OpenMode.ForRead) as DBText;
if (dbText.TextString.Contains("testText")
{
return dbText.TextString;
}
}
return "";
}
else
{
return "";
}
}
}
But now I am converting my program to side-load the underlying databases because it was taking too long for the program to open and close every .DWG file. The problem is that now I am using
db.ReadDwgFile(currentDWG, FileOpenMode.OpenForReadAndAllShare, true, string.Empty);
to read files without actually opening them so I can't use
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor
and
ed.SelectAll(sf) for the selection filter strategy I was using earlier because the document isn't actually open. So how can I can get all of the text entities on each layer named "testLayer" without actually opening the DWG file?
In a 'side database', to mimic SelectAll, you have to iterate through all entities in all the layouts and check the entity layer.
EDIT: In a 'side database', to mimic SelectAll, you have to iterate through all entities in all the layouts and check the entity type and layer.
private IEnumerable<ObjectId> GetTextEntitiesOnLayer(Database db, string layerName)
{
using (var tr = db.TransactionManager.StartOpenCloseTransaction())
{
var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
foreach (ObjectId btrId in blockTable)
{
var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
var textClass = RXObject.GetClass(typeof(DBText));
if (btr.IsLayout)
{
foreach (ObjectId id in btr)
{
if (id.ObjectClass == textClass)
{
var text = (DBText)tr.GetObject(id, OpenMode.ForRead);
if (text.Layer.Equals(layerName, System.StringComparison.CurrentCultureIgnoreCase))
{
yield return id;
}
}
}
}
}
}
}

Multithreading with Windows Store Applications

We are currently creating a Windows Store Application which gains information from an RSS feed and inputs this information into an ObservableCollection. The issue we are having is when the information is being gained, the Applications UI becomes unresponsive.
In order to get around this, I thought about creating a new thread and calling the method within this. Though, after some research we realised that this was no longer possible in Windows Store Apps. How can we get around this?
The method that collects the information is below.
public void getFeed()
{
setupImages();
string[] feedUrls = new string[] {
"http://www.igadgetos.co.uk/blog/category/gadget-news/feed/",
"http://www.igadgetos.co.uk/blog/category/gadget-reviews/feed/",
"http://www.igadgetos.co.uk/blog/category/videos/feed/",
"http://www.igadgetos.co.uk/blog/category/gaming/feed/",
"http://www.igadgetos.co.uk/blog/category/jailbreak-2/feed/",
"http://www.igadgetos.co.uk/blog/category/kickstarter/feed/",
"http://www.igadgetos.co.uk/blog/category/cars-2/feed/",
"http://www.igadgetos.co.uk/blog/category/software/feed/",
"http://www.igadgetos.co.uk/blog/category/updates/feed/"
};
{
try
{
XNamespace dc = "http://purl.org/dc/elements/1.1/";
XNamespace content = "http://purl.org/rss/1.0/modules/content/";
foreach (var feedUrl in feedUrls)
{
var doc = XDocument.Load(feedUrl);
var feed = doc.Descendants("item").Select(c => new ArticleItem() //Creates a copy of the ArticleItem Class.
{
Title = c.Element("title").Value,
//There are another 4 of these.
Post = stripTags(c.Element(content + "encoded").Value) }
).OrderByDescending(c => c.PubDate);
this.moveItems = feed.ToList();
foreach (var item in moveItems)
{
item.ID = feedItems.Count;
feedItems.Add(item);
}
}
lastUpdated = DateTime.Now;
}
catch
{
MessageDialog popup = new MessageDialog("An error has occured downloading the feed, please try again later.");
popup.Commands.Add(new UICommand("Okay"));
popup.Title = "ERROR";
popup.ShowAsync();
}
}
}
How would we be able to cause the Application to not freeze as we gain this information, as Threading is not possible within Windows Store Applications.
E.g - We planned to use;
Thread newThread = new Thread(getFeed);
newThread.Start
You need to use the well documented async pattern for your operations that happen on the UI thread. The link given by Paul-Jan in the comments is where you need to start. http://msdn.microsoft.com/en-us/library/windows/apps/hh994635.aspx

Categories

Resources