Implemented printing.
This commit is contained in:
@@ -186,17 +186,17 @@ namespace UCalc
|
||||
}
|
||||
}
|
||||
|
||||
public bool Print()
|
||||
public void Print()
|
||||
{
|
||||
if (Model.Root.Errors.Count > 0)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Bitte beheben Sie zuerst die angezeigten Fehler, bevor Sie das Dokument drucken können.",
|
||||
"Fehler!", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
new PrintWindow(Model) {Owner = this}.ShowDialog();
|
||||
}
|
||||
|
||||
private void OnDetailsTabSelected(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using UCalc.Controls;
|
||||
using UCalc.Data;
|
||||
@@ -26,5 +27,33 @@ namespace UCalc
|
||||
|
||||
public static readonly ImmutableList<string> CostDivisionStrs =
|
||||
((CostDivision[]) Enum.GetValues(typeof(CostDivision))).Select(value => value.AsString()).ToImmutableList();
|
||||
|
||||
public static readonly double DinA4Width;
|
||||
public static readonly double DinA4Height;
|
||||
public static readonly Thickness DinA4Padding;
|
||||
|
||||
public static double DinA4ContentWidth => DinA4Width - DinA4Padding.Left - DinA4Padding.Right;
|
||||
|
||||
public static readonly double PrintDefaultFontSize;
|
||||
public static readonly double PrintSubjectFontSize;
|
||||
public static readonly double PrintNewlineFontSize;
|
||||
|
||||
static Constants()
|
||||
{
|
||||
var converter = new LengthConverter();
|
||||
// ReSharper disable PossibleNullReferenceException
|
||||
DinA4Width = (double) converter.ConvertFromInvariantString("29.7cm");
|
||||
DinA4Height = (double) converter.ConvertFromInvariantString("42cm");
|
||||
var dinA4MarginLeftRight = (double) converter.ConvertFromInvariantString("3.18cm");
|
||||
var dinA4MarginTopBottom = (double) converter.ConvertFromInvariantString("2.54cm");
|
||||
|
||||
PrintDefaultFontSize = (double) converter.ConvertFromInvariantString("14pt");
|
||||
PrintSubjectFontSize = (double) converter.ConvertFromInvariantString("16pt");
|
||||
PrintNewlineFontSize = (double) converter.ConvertFromInvariantString("4pt");
|
||||
// ReSharper restore PossibleNullReferenceException
|
||||
|
||||
DinA4Padding = new Thickness(dinA4MarginLeftRight, dinA4MarginTopBottom, dinA4MarginLeftRight,
|
||||
dinA4MarginTopBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Xps.Packaging;
|
||||
using System.Windows.Xps.Serialization;
|
||||
|
||||
namespace UCalc.Controls
|
||||
{
|
||||
public class PrintableDocument : IDisposable
|
||||
{
|
||||
private static readonly Uri DocUri = new Uri($"pack://mietrechner{new Guid()}.xps");
|
||||
private readonly Package _package;
|
||||
private readonly XpsDocument _document;
|
||||
|
||||
private int PageCount =>
|
||||
_document.GetFixedDocumentSequence()!.References.First().GetDocument(false)!.Pages.Count;
|
||||
|
||||
public PrintableDocument(IDocumentPaginatorSource source)
|
||||
{
|
||||
_package = Package.Open(new MemoryStream(), FileMode.Create, FileAccess.ReadWrite);
|
||||
|
||||
PackageStore.AddPackage(DocUri, _package);
|
||||
|
||||
_document = new XpsDocument(_package, CompressionOption.SuperFast, DocUri.AbsoluteUri);
|
||||
var manager = new XpsSerializationManager(new XpsPackagingPolicy(_document), false);
|
||||
|
||||
var paginator = source.DocumentPaginator;
|
||||
manager.SaveAsXaml(paginator);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
((IDisposable) _document).Dispose();
|
||||
((IDisposable) _package).Dispose();
|
||||
PackageStore.RemovePackage(DocUri);
|
||||
}
|
||||
|
||||
public void PreviewIn(DocumentViewer viewer)
|
||||
{
|
||||
viewer.Document = _document.GetFixedDocumentSequence();
|
||||
}
|
||||
|
||||
public void Print(string description)
|
||||
{
|
||||
var dialog = new PrintDialog {UserPageRangeEnabled = true, MinPage = 1, MaxPage = (uint) PageCount};
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
var documentSequence = _document.GetFixedDocumentSequence();
|
||||
Package convPackage = null;
|
||||
XpsDocument convDocument = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (dialog.PageRangeSelection == PageRangeSelection.UserPages)
|
||||
{
|
||||
convDocument = ExtractPages(_document, dialog.PageRange.PageFrom - 1,
|
||||
dialog.PageRange.PageTo - 1, out convPackage);
|
||||
documentSequence = convDocument.GetFixedDocumentSequence();
|
||||
}
|
||||
|
||||
dialog.PrintDocument(documentSequence!.DocumentPaginator, description);
|
||||
}
|
||||
finally
|
||||
{
|
||||
convDocument?.Close();
|
||||
convPackage?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static XpsDocument ExtractPages(XpsDocument source, int fromPage, int toPage, out Package package)
|
||||
{
|
||||
package = Package.Open(new MemoryStream(), FileMode.Create, FileAccess.ReadWrite);
|
||||
|
||||
var docUri = new Uri("pack://mietrechnerTempTicket.xps");
|
||||
PackageStore.RemovePackage(docUri);
|
||||
PackageStore.AddPackage(docUri, package);
|
||||
|
||||
var document = new XpsDocument(package, CompressionOption.SuperFast, docUri.AbsoluteUri);
|
||||
var pages = source.GetFixedDocumentSequence()!.References.First().GetDocument(false)!.Pages;
|
||||
|
||||
var documentReference = new DocumentReference();
|
||||
var fixedDocument = new FixedDocument();
|
||||
documentReference.SetDocument(fixedDocument);
|
||||
|
||||
for (var i = fromPage; i <= toPage; ++i)
|
||||
{
|
||||
var page = pages[i];
|
||||
var pageContentChild = new PageContent {Source = page.Source};
|
||||
((IUriContext) pageContentChild).BaseUri = ((IUriContext) page).BaseUri;
|
||||
pageContentChild.GetPageRoot(false);
|
||||
fixedDocument.Pages.Add(pageContentChild);
|
||||
}
|
||||
|
||||
var documentSequence = new FixedDocumentSequence();
|
||||
documentSequence.References.Add(documentReference);
|
||||
|
||||
var writer = XpsDocument.CreateXpsDocumentWriter(document);
|
||||
writer.Write(documentSequence);
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,15 +10,17 @@ namespace UCalc.Data
|
||||
{
|
||||
public Tenant Tenant { get; }
|
||||
public IReadOnlyDictionary<Cost, CostCalculationResult> Costs { get; }
|
||||
public decimal SubTotalAmount { get; }
|
||||
public decimal TotalAmount { get; }
|
||||
public string Details { get; }
|
||||
public string DetailsForLandlord { get; }
|
||||
|
||||
public TenantCalculationResult(Tenant tenant, IReadOnlyDictionary<Cost, CostCalculationResult> costs,
|
||||
decimal totalAmount, string details, string detailsForLandlord)
|
||||
decimal subTotalAmount, decimal totalAmount, string details, string detailsForLandlord)
|
||||
{
|
||||
Tenant = tenant;
|
||||
Costs = costs;
|
||||
SubTotalAmount = subTotalAmount;
|
||||
TotalAmount = totalAmount;
|
||||
Details = details;
|
||||
DetailsForLandlord = detailsForLandlord;
|
||||
@@ -616,6 +618,7 @@ namespace UCalc.Data
|
||||
var str = $"Zwischensumme: {totalAmount.CeilToString()} €\n";
|
||||
str += $"Bereits bezahlt: {tenant.PaidRent.CeilToString()} €\n\n";
|
||||
|
||||
var subTotalAmount = totalAmount;
|
||||
totalAmount -= tenant.PaidRent;
|
||||
totalAmount = totalAmount.Ceil2();
|
||||
|
||||
@@ -624,7 +627,7 @@ namespace UCalc.Data
|
||||
details.Append(str);
|
||||
detailsLandlord.Append(str);
|
||||
|
||||
return new TenantCalculationResult(tenant, costResults, totalAmount, details.ToString(),
|
||||
return new TenantCalculationResult(tenant, costResults, subTotalAmount, totalAmount, details.ToString(),
|
||||
detailsLandlord.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace UCalc.Pages
|
||||
|
||||
private void OnAboutClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
MessageBox.Show("MietRechner Version 2.0\n\nCopyright © 2020 by Tobias Erbshäußer", "Über MietRechner",
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
<Window x:Class="UCalc.PrintWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:UCalc"
|
||||
xmlns:controls="clr-namespace:UCalc.Controls"
|
||||
xmlns:drawing="clr-namespace:System.Drawing;assembly=System.Drawing.Primitives"
|
||||
mc:Ignorable="d"
|
||||
Title="Druckvorschau"
|
||||
Width="500"
|
||||
Height="600"
|
||||
MinWidth="400"
|
||||
MinHeight="300"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
ShowInTaskbar="False"
|
||||
Icon="logo.ico">
|
||||
|
||||
<DockPanel>
|
||||
<FlowDocumentScrollViewer x:Name="ScrollViewer"
|
||||
Visibility="Collapsed">
|
||||
<FlowDocument x:Name="Document"
|
||||
PageWidth="{x:Static local:Constants.DinA4Width}"
|
||||
PageHeight="{x:Static local:Constants.DinA4Height}"
|
||||
PagePadding="{x:Static local:Constants.DinA4Padding}"
|
||||
ColumnWidth="{x:Static local:Constants.DinA4ContentWidth}" />
|
||||
</FlowDocumentScrollViewer>
|
||||
|
||||
<DocumentViewer x:Name="Viewer">
|
||||
<DocumentViewer.Resources>
|
||||
<Style TargetType="{x:Type DocumentViewer}">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{x:Null}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type DocumentViewer}">
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Focusable="False">
|
||||
<Grid KeyboardNavigation.TabNavigation="Local">
|
||||
<Grid.Background>
|
||||
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
|
||||
</Grid.Background>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ToolBar ToolBarTray.IsLocked="True"
|
||||
KeyboardNavigation.TabNavigation="Continue">
|
||||
<Button PreviewMouseUp="OnPrintClick">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="4, 4, 0, 4">
|
||||
<Canvas Width="512" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M448 192V77.25c0-8.49-3.37-16.62-9.37-22.63L393.37 9.37c-6-6-14.14-9.37-22.63-9.37H96C78.33 0 64 14.33 64 32v160c-35.35 0-64 28.65-64 64v112c0 8.84 7.16 16 16 16h48v96c0 17.67 14.33 32 32 32h320c17.67 0 32-14.33 32-32v-96h48c8.84 0 16-7.16 16-16V256c0-35.35-28.65-64-64-64zm-64 256H128v-96h256v96zm0-224H128V64h192v48c0 8.84 7.16 16 16 16h48v96zm48 72c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Drucken"
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
|
||||
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||
|
||||
<Button Click="OnTenantSelectorClick"
|
||||
Tag="{Binding Path=TenantMenuItems, RelativeSource={RelativeSource AncestorType=local:PrintWindow}}">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
DockPanel.Dock="Right">
|
||||
<Canvas Width="320" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Mieter auswählen"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
|
||||
<Button.ContextMenu>
|
||||
<ContextMenu
|
||||
ItemsSource="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
|
||||
<ContextMenu.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type MenuItem}">
|
||||
<EventSetter Event="Click" Handler="OnTenantMenuItemClick" />
|
||||
<Setter Property="IsChecked" Value="{Binding Selected}"/>
|
||||
<Setter Property="Header" Value="{Binding Name}" />
|
||||
</Style>
|
||||
</ContextMenu.ItemContainerStyle>
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
|
||||
</Button>
|
||||
|
||||
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||
|
||||
<Button Command="NavigationCommands.IncreaseZoom"
|
||||
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="4, 4, 0, 4">
|
||||
<Canvas Width="512" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M304 192v32c0 6.6-5.4 12-12 12h-56v56c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-56h-56c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h56v-56c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v56h56c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Vergrößern"
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
|
||||
<Button Command="NavigationCommands.DecreaseZoom"
|
||||
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="4, 4, 0, 4">
|
||||
<Canvas Width="512" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M304 192v32c0 6.6-5.4 12-12 12H124c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Verkleinern"
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
|
||||
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||
|
||||
<Button Command="DocumentViewer.FitToWidthCommand"
|
||||
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="4, 4, 0, 4">
|
||||
<Canvas Width="448" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M432 32H16A16 16 0 0 0 0 48v80a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16v-16h120v112h-24a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-24V112h120v16a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zm-68.69 260.69C354 283.36 336 288.36 336 304v48H112v-48c0-14.31-17.31-21.32-27.31-11.31l-80 80a16 16 0 0 0 0 22.62l80 80C94 484.64 112 479.64 112 464v-48h224v48c0 14.31 17.31 21.33 27.31 11.31l80-80a16 16 0 0 0 0-22.62z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Ganze Breite"
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
|
||||
<Button Command="DocumentViewer.FitToMaxPagesAcrossCommand"
|
||||
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
|
||||
CommandParameter="1">
|
||||
<DockPanel>
|
||||
<Viewbox Stretch="Uniform"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="4, 4, 0, 4">
|
||||
<Canvas Width="512" Height="512">
|
||||
<Canvas.RenderTransform>
|
||||
<TranslateTransform X="0" Y="0" />
|
||||
</Canvas.RenderTransform>
|
||||
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||
<Path.Data>
|
||||
<PathGeometry
|
||||
Figures="M200 288H88c-21.4 0-32.1 25.8-17 41l32.9 31-99.2 99.3c-6.2 6.2-6.2 16.4 0 22.6l25.4 25.4c6.2 6.2 16.4 6.2 22.6 0L152 408l31.1 33c15.1 15.1 40.9 4.4 40.9-17V312c0-13.3-10.7-24-24-24zm112-64h112c21.4 0 32.1-25.9 17-41l-33-31 99.3-99.3c6.2-6.2 6.2-16.4 0-22.6L481.9 4.7c-6.2-6.2-16.4-6.2-22.6 0L360 104l-31.1-33C313.8 55.9 288 66.6 288 88v112c0 13.3 10.7 24 24 24zm96 136l33-31.1c15.1-15.1 4.4-40.9-17-40.9H312c-13.3 0-24 10.7-24 24v112c0 21.4 25.9 32.1 41 17l31-32.9 99.3 99.3c6.2 6.2 16.4 6.2 22.6 0l25.4-25.4c6.2-6.2 6.2-16.4 0-22.6L408 360zM183 71.1L152 104 52.7 4.7c-6.2-6.2-16.4-6.2-22.6 0L4.7 30.1c-6.2 6.2-6.2 16.4 0 22.6L104 152l-33 31.1C55.9 198.2 66.6 224 88 224h112c13.3 0 24-10.7 24-24V88c0-21.3-25.9-32-41-16.9z"
|
||||
FillRule="NonZero" />
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
|
||||
<Label Content="Ganze Seite"
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
</ToolBar>
|
||||
|
||||
<ScrollViewer Grid.Row="1"
|
||||
CanContentScroll="true"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
x:Name="PART_ContentHost"
|
||||
IsTabStop="true">
|
||||
<ScrollViewer.Background>
|
||||
<LinearGradientBrush EndPoint="0.5,1"
|
||||
StartPoint="0.5,0">
|
||||
<GradientStop Color="{DynamicResource ControlLightColor}"
|
||||
Offset="0" />
|
||||
<GradientStop Color="{DynamicResource ControlMediumColor}"
|
||||
Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</ScrollViewer.Background>
|
||||
</ScrollViewer>
|
||||
|
||||
<ContentControl Grid.Row="2"
|
||||
x:Name="PART_FindToolBarHost" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</DocumentViewer.Resources>
|
||||
</DocumentViewer>
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using UCalc.Annotations;
|
||||
using UCalc.Controls;
|
||||
using UCalc.Data;
|
||||
using UCalc.Models;
|
||||
|
||||
namespace UCalc
|
||||
{
|
||||
public class TenantMenuItem : INotifyPropertyChanged
|
||||
{
|
||||
public Tenant Tenant { get; }
|
||||
public bool None { get; }
|
||||
private bool _selected;
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get => _selected;
|
||||
set
|
||||
{
|
||||
if (value == _selected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_selected = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public TenantMenuItem(Tenant tenant, bool none)
|
||||
{
|
||||
Tenant = tenant;
|
||||
None = none;
|
||||
Selected = tenant != null;
|
||||
}
|
||||
|
||||
public string Name => Tenant != null ? Tenant.Name : None ? "Kein Mieter" : "Alle Mieter";
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[NotifyPropertyChangedInvocator]
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class PrintWindow
|
||||
{
|
||||
public Billing Billing { get; }
|
||||
public IReadOnlyList<TenantMenuItem> TenantMenuItems { get; }
|
||||
private PrintableDocument _document;
|
||||
|
||||
|
||||
public PrintWindow(Model model)
|
||||
{
|
||||
Billing = model.Dump();
|
||||
TenantMenuItems = new[] {new TenantMenuItem(null, false), new TenantMenuItem(null, true)}.Concat(
|
||||
Billing.Tenants.Select(tenant => new TenantMenuItem(tenant, false))).ToList();
|
||||
|
||||
foreach (var item in TenantMenuItems)
|
||||
{
|
||||
item.PropertyChanged += OnSelectedTenantChanged;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Preview();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
|
||||
_document?.Dispose();
|
||||
}
|
||||
|
||||
private void Preview()
|
||||
{
|
||||
Document.Blocks.Clear();
|
||||
|
||||
foreach (var item in TenantMenuItems)
|
||||
{
|
||||
if (!item.Selected)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result = BillingCalculator.CalculateForTenant(Billing, item.Tenant);
|
||||
PreviewForSingleTenant(item.Tenant, result);
|
||||
}
|
||||
|
||||
_document?.Dispose();
|
||||
_document = new PrintableDocument(Document);
|
||||
_document.PreviewIn(Viewer);
|
||||
}
|
||||
|
||||
private static void AddLineBreaks(TableRowGroup rowGroup, int count)
|
||||
{
|
||||
var row = new TableRow();
|
||||
rowGroup.Rows.Add(row);
|
||||
|
||||
var cell = new TableCell {ColumnSpan = 2};
|
||||
row.Cells.Add(cell);
|
||||
cell.Blocks.Add(new Paragraph(new Run(new string('\n', count))
|
||||
{FontSize = Constants.PrintNewlineFontSize}));
|
||||
}
|
||||
|
||||
private static void AddText(TableRowGroup rowGroup, string text, double? fontSize = null,
|
||||
bool alignRight = false)
|
||||
{
|
||||
var row = new TableRow();
|
||||
rowGroup.Rows.Add(row);
|
||||
|
||||
var cell = new TableCell {ColumnSpan = 2};
|
||||
row.Cells.Add(cell);
|
||||
|
||||
if (alignRight)
|
||||
{
|
||||
cell.TextAlignment = TextAlignment.Right;
|
||||
}
|
||||
|
||||
var paragraph = new Paragraph(new Run(text));
|
||||
cell.Blocks.Add(paragraph);
|
||||
|
||||
if (fontSize != null)
|
||||
{
|
||||
paragraph.FontSize = fontSize.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void PreviewForSingleTenant(Tenant tenant, TenantCalculationResult result)
|
||||
{
|
||||
var section = new Section {BreakPageBefore = true, FontSize = Constants.PrintDefaultFontSize};
|
||||
Document.Blocks.Add(section);
|
||||
|
||||
var table = new Table {CellSpacing = 0};
|
||||
section.Blocks.Add(table);
|
||||
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||
|
||||
var rowGroup = new TableRowGroup();
|
||||
table.RowGroups.Add(rowGroup);
|
||||
|
||||
void AddLineBreaks(int count)
|
||||
{
|
||||
PrintWindow.AddLineBreaks(rowGroup, count);
|
||||
}
|
||||
|
||||
void AddText(string text, double? fontSize = null, bool alignRight = false)
|
||||
{
|
||||
PrintWindow.AddText(rowGroup, text, fontSize, alignRight);
|
||||
}
|
||||
|
||||
void AddCost(string name, decimal amount, bool isLast = false)
|
||||
{
|
||||
var row2 = new TableRow();
|
||||
rowGroup.Rows.Add(row2);
|
||||
|
||||
if (isLast)
|
||||
{
|
||||
row2.Background = Brushes.LightGray;
|
||||
}
|
||||
|
||||
var cell2 = new TableCell
|
||||
{BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1, 1, 0, isLast ? 1 : 0)};
|
||||
row2.Cells.Add(cell2);
|
||||
|
||||
cell2.Blocks.Add(new Paragraph(new Run(name)) {Padding = new Thickness(6)});
|
||||
|
||||
cell2 = new TableCell
|
||||
{
|
||||
BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1, 1, 1, isLast ? 1 : 0),
|
||||
TextAlignment = TextAlignment.Right
|
||||
};
|
||||
row2.Cells.Add(cell2);
|
||||
|
||||
cell2.Blocks.Add(new Paragraph(new Run($"{amount.CeilToString()} €")) {Padding = new Thickness(6)});
|
||||
}
|
||||
|
||||
AddText(
|
||||
$"{Billing.Landlord.Salutation.AsString()} {Billing.Landlord.Name}\n{DateTime.Now.ToString(Constants.DateFormat)}\n\n{Billing.Landlord.Address.Street} {Billing.Landlord.Address.HouseNumber}\n{Billing.Landlord.Address.Postcode} {Billing.Landlord.Address.City}\nTelefon: {Billing.Landlord.Phone}\nEmail: {Billing.Landlord.MailAddress}");
|
||||
|
||||
AddLineBreaks(2);
|
||||
|
||||
AddText(
|
||||
$"{tenant.Salutation.AsString()} {tenant.Name}\n{Billing.House.Address.Street} {Billing.House.Address.HouseNumber}\n{Billing.House.Address.Postcode} {Billing.House.Address.City}",
|
||||
null, true);
|
||||
|
||||
AddLineBreaks(4);
|
||||
|
||||
AddText($"{tenant.Salutation.AsString()} {tenant.Name}");
|
||||
|
||||
AddLineBreaks(1);
|
||||
|
||||
AddText(
|
||||
$"Nebenkostenabrechnung vom {Billing.StartDate.ToString(Constants.DateFormat)} zum {Billing.EndDate.ToString(Constants.DateFormat)}",
|
||||
Constants.PrintSubjectFontSize);
|
||||
|
||||
AddLineBreaks(1);
|
||||
|
||||
if (!string.IsNullOrEmpty(tenant.CustomMessage1))
|
||||
{
|
||||
AddText(tenant.CustomMessage1);
|
||||
|
||||
AddLineBreaks(1);
|
||||
}
|
||||
|
||||
foreach (var (cost, costResult) in result.Costs)
|
||||
{
|
||||
AddCost(cost.Name, costResult.TotalAmount);
|
||||
}
|
||||
|
||||
AddCost("Zwischensumme", result.SubTotalAmount);
|
||||
AddCost("Bereits gezahlt", tenant.PaidRent);
|
||||
AddCost(result.TotalAmount > 0 ? "Einmalige Nachzahlung" : "Einmalige Rückzahlung", result.TotalAmount,
|
||||
true);
|
||||
|
||||
AddLineBreaks(2);
|
||||
|
||||
if (result.TotalAmount > 0)
|
||||
{
|
||||
AddText(
|
||||
$"Bitte überweisen Sie den einmaligen Betrag von {result.TotalAmount.CeilToString()} € auf das untenstehende Konto.");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddText(
|
||||
$"Der einmalige Betrag von {result.TotalAmount.CeilToString()} € wird in den nächsten Tagen auf Ihr Konto überwiesen.");
|
||||
}
|
||||
|
||||
AddLineBreaks(1);
|
||||
|
||||
if (!string.IsNullOrEmpty(tenant.CustomMessage2))
|
||||
{
|
||||
AddText(tenant.CustomMessage2);
|
||||
AddLineBreaks(1);
|
||||
}
|
||||
|
||||
AddText("Kontoverbindung:");
|
||||
AddText($"IBAN: {Billing.Landlord.BankAccount.Iban}");
|
||||
AddText($"BIC: {Billing.Landlord.BankAccount.Bic}");
|
||||
AddText($"Name der Bank: {Billing.Landlord.BankAccount.BankName}");
|
||||
|
||||
AddLineBreaks(2);
|
||||
|
||||
AddText("Mit freundlichen Grüßen");
|
||||
|
||||
if (result.Costs.Any(t => t.Key.DisplayInBill))
|
||||
{
|
||||
PreviewForSingleTenantDetails(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void PreviewForSingleTenantDetails(TenantCalculationResult result)
|
||||
{
|
||||
var section = new Section {BreakPageBefore = true, FontSize = Constants.PrintDefaultFontSize};
|
||||
Document.Blocks.Add(section);
|
||||
|
||||
var table = new Table {CellSpacing = 0};
|
||||
section.Blocks.Add(table);
|
||||
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||
|
||||
var rowGroup = new TableRowGroup();
|
||||
table.RowGroups.Add(rowGroup);
|
||||
|
||||
void AddLineBreaks(int count)
|
||||
{
|
||||
PrintWindow.AddLineBreaks(rowGroup, count);
|
||||
}
|
||||
|
||||
void AddText(string text, double? fontSize = null, bool alignRight = false)
|
||||
{
|
||||
PrintWindow.AddText(rowGroup, text, fontSize, alignRight);
|
||||
}
|
||||
|
||||
AddText("Details zur Berechnung:");
|
||||
|
||||
AddLineBreaks(1);
|
||||
|
||||
foreach (var (cost, costResult) in result.Costs)
|
||||
{
|
||||
if (!cost.DisplayInBill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddText(costResult.Details);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPrintClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_document.Print(
|
||||
$"MietRechner Abrechnung {Billing.StartDate.ToString(Constants.DateFormat)} - {Billing.EndDate.ToString(Constants.DateFormat)}");
|
||||
}
|
||||
|
||||
private void OnSelectedTenantChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
Preview();
|
||||
}
|
||||
|
||||
private void OnTenantSelectorClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var button = (Button) sender;
|
||||
var contextMenu = button.ContextMenu;
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
contextMenu.PlacementTarget = button;
|
||||
contextMenu.Placement = PlacementMode.Bottom;
|
||||
contextMenu.IsOpen = true;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTenantMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (TenantMenuItem) ((MenuItem) sender).DataContext;
|
||||
|
||||
if (item.Tenant == null)
|
||||
{
|
||||
foreach (var item2 in TenantMenuItems)
|
||||
{
|
||||
if (item2.Tenant != null)
|
||||
{
|
||||
item2.Selected = !item.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Selected = !item.Selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,9 @@
|
||||
<Page Update="CostEntryDetailsWindow.xaml">
|
||||
<Generator></Generator>
|
||||
</Page>
|
||||
<Page Update="PrintWindow.xaml">
|
||||
<Generator></Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -94,6 +97,9 @@
|
||||
<Compile Update="CostEntryDetailsWindow.xaml.cs">
|
||||
<DependentUpon>CostEntryDetailsWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="PrintWindow.xaml.cs">
|
||||
<DependentUpon>PrintWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user