private void initUI() { double pnlWidth = (double)AppLib.GetAppGlobalValue("categoriesPanelWidth"); double pnlHeight = (double)AppLib.GetAppGlobalValue("categoriesPanelHeight"); double promoFontSize, dH, d1, dKoefPortionCount; double pnlW, titleFontSize; // грид блюд double dishesPanelWidth = (double)AppLib.GetAppGlobalValue("dishesPanelWidth"); double dishesPanelHeight = (double)AppLib.GetAppGlobalValue("dishesPanelHeight"); scrollDishes.Height = dishesPanelHeight; scrollDishes.Width = dishesPanelWidth; double dishNameFontSize, dishUnitFontSize; string backgroundImage; Style stl; Setter str; // дизайн вертикальный: панель меню СВЕРХУ if (AppLib.IsAppVerticalLayout) { DockPanel.SetDock(gridMenuSide, Dock.Top); // menuSidePanelLogo.Background = (Brush)AppLib.GetAppGlobalValue("appBackgroundColor"); // грид меню //pnlHeight *= 0.8; gridMenuSide.Height = pnlHeight; gridMenuSide.Width = pnlWidth; // панель меню на всю ширину экрана dH = pnlHeight / 10d; gridMenuSide.RowDefinitions[0].Height = new GridLength(3.0 * dH); gridMenuSide.RowDefinitions[1].Height = new GridLength(0.0 * dH); gridMenuSide.RowDefinitions[2].Height = new GridLength(3.5 * dH); gridMenuSide.RowDefinitions[3].Height = new GridLength(0.0 * dH); gridMenuSide.RowDefinitions[4].Height = new GridLength(0.0 * dH); gridMenuSide.RowDefinitions[5].Height = new GridLength(3.5 * dH); // stackPanel для Logo gridMenuSide.Children.Remove(imageLogo); StackPanel pnlLogo = new StackPanel(); pnlLogo.Orientation = Orientation.Horizontal; pnlLogo.Background = new SolidColorBrush(Color.FromRgb(0x62, 0x1C, 0x55)); pnlW = gridMenuSide.Width - 2.0 * dH; // перенести кнопку Назад gridMenuSide.Children.Remove(btnReturn); pnlLogo.Children.Add(btnReturn); btnReturn.Width = 0.3 * pnlW; // общая ширина = ширина элемента + отступы справа/слева txtReturn.HorizontalAlignment = HorizontalAlignment.Left; btnReturn.Margin = new Thickness(dH, 0, 0, 0); btnReturn.Background = pnlLogo.Background; // языковые кнопки gridMenuSide.Children.Remove(gridLang); gridLang.Height = 2.0 * dH; // необходимо для расчета размера внутренних кнопок gridLang.Width = 0.2 * pnlW; gridLang.Margin = new Thickness(0.1 * pnlW, 0, 0.1 * pnlW, 0); pnlLogo.Children.Add(gridLang); gridLang.Visibility = Visibility.Visible; // языковые кнопки, фон для внешних Border, чтобы они были кликабельные btnLangUa.Background = pnlLogo.Background; btnLangRu.Background = pnlLogo.Background; btnLangEn.Background = pnlLogo.Background; double dMin = Math.Min(gridLang.Height, gridMenuSide.Width / (0.3 + 1.0 + 0.3 + 1.0 + 0.3 + 1.0 + 0.3)); double dLangSize = 0.7 * dMin; setLngInnerBtnSizes(btnLangUaInner, lblLangUa, dLangSize); setLngInnerBtnSizes(btnLangRuInner, lblLangRu, dLangSize); setLngInnerBtnSizes(btnLangEnInner, lblLangEn, dLangSize); // перенести промокод gridMenuSide.Children.Remove(gridPromoCode); gridPromoCode.ColumnDefinitions[3].Width = new GridLength(0.0 * dH); gridPromoCode.Width = 0.3 * pnlW; gridPromoCode.HorizontalAlignment = HorizontalAlignment.Right; gridPromoCode.Height = 1.5 * dH; promoFontSize = 0.5 * dH; pnlLogo.Children.Add(gridPromoCode); Grid.SetRow(pnlLogo, 0); gridMenuSide.Children.Add(pnlLogo); // строка с общей стоимостью pnlTotal.Orientation = Orientation.Horizontal; txtOrderPrice.Margin = new Thickness(20, 0, 0, 0); pnlTotalLabel.FontSize = (double)AppLib.GetAppGlobalValue("appFontSize2"); txtOrderPrice.FontSize = (double)AppLib.GetAppGlobalValue("appFontSize1"); // кнопка Оформить btnPrintCheck.Margin = new Thickness(dH, 0.0 * dH, dH, 0.8 * dH); btnPrintCheck.CornerRadius = new CornerRadius((double)AppLib.GetAppGlobalValue("cornerRadiusButton")); txtPrintCheck.FontSize = (double)AppLib.GetAppGlobalValue("appFontSize4"); txtPrintCheck.FontWeight = FontWeights.Bold; gridMenuSide.Children.Remove(txtCashier); pnlPrintCheck.Children.Add(txtCashier); txtCashier.Style = (Style)this.Resources["goToCashierVer"]; // фон backgroundImage = AppLib.GetImageFullFileName((string)AppLib.GetAppGlobalValue("BackgroundImageVertical")); setLangButtonStyle(true); // "включить" текущую языковую кнопку // панели блюд dishBorderHeight = (dishesPanelHeight - dishesListTitle.ActualHeight) / 6.0; titleFontSize = 0.015 * dishesPanelHeight; dishNameFontSize = 0.09 * dishBorderHeight; dishUnitFontSize = 0.08 * dishBorderHeight; dKoefPortionCount = 1.5d; // отступы кнопок изменения кол-ва блюда setStylePropertyValue("dishPortionImageStyle", "Margin", new Thickness(0.03 * dishBorderHeight)); setStylePropertyValue("dishDelImageStyle", "Margin", new Thickness(0.1 * dishBorderHeight)); } // дизайн горизонтальный: панель меню слева else { DockPanel.SetDock(dockMain, Dock.Left); // грид меню gridMenuSide.Height = pnlHeight; gridMenuSide.Width = pnlWidth; dH = pnlHeight / 13d; // промокод gridPromoCode.Height = 0.6 * dH; gridPromoCode.Margin = new Thickness(0, 0, 0, 0.4 * dH); promoFontSize = 0.3 * gridPromoCode.Height; txtCashier.Margin = new Thickness(0.5 * dH, 0, 0.5 * dH, 0); // фон backgroundImage = AppLib.GetImageFullFileName((string)AppLib.GetAppGlobalValue("BackgroundImageHorizontal")); dishBorderHeight = (dishesPanelHeight - dishesListTitle.ActualHeight) / 4.0; titleFontSize = 0.02 * dishesPanelHeight; dishNameFontSize = 0.09 * dishBorderHeight; dishUnitFontSize = 0.08 * dishBorderHeight; dKoefPortionCount = 1.5; // отступы кнопок изменения кол-ва блюда setStylePropertyValue("dishPortionImageStyle", "Margin", new Thickness(0.03 * dishBorderHeight)); setStylePropertyValue("dishDelImageStyle", "Margin", new Thickness(0.15 * dishBorderHeight)); } // фон imgBackground.Source = ImageHelper.GetBitmapImage(backgroundImage); // яркость фона imgBackground.Opacity = (double)AppLib.GetAppGlobalValue("BackgroundImageBrightness", 0.3); // высота рамки блюда в заказе, из стиля setStylePropertyValue("dishBorderStyle", "MinHeight", dishBorderHeight); // элементы в строке блюда, относительно ее высоты dishBorderHeight // внутренние поля в рамке блюда setStylePropertyValue("dishItemStyle", "Padding", new Thickness(0.06 * dishBorderHeight, 0.05 * dishBorderHeight, 0, 0.05 * dishBorderHeight)); // изображение блюда (1:1.33) setStylePropertyValue("dishImageBorderStyle", "Height", 1.0 * dishBorderHeight); setStylePropertyValue("dishImageBorderStyle", "Width", 1.33 * dishBorderHeight); // наименование блюда setStylePropertyValue("dishNameStyle", "FontSize", dishNameFontSize); // ед.изм. блюда setStylePropertyValue("dishUnitStyle", "FontSize", dishUnitFontSize); // маркеры блюда setStylePropertyValue("dishMarksItemStyle", "Height", 1.2 * dishUnitFontSize); // заголовок ингредиентов setStylePropertyValue("dishIngrTitleStyle", "FontSize", dishUnitFontSize); // наименование и цена ингредиента setStylePropertyValue("dishIngrStyle", "FontSize", dishUnitFontSize); setStylePropertyValue("dishIngrDelImageStyle", "Width", 2.5 * dishUnitFontSize); setStylePropertyValue("dishIngrDelImageStyle", "Padding", new Thickness(0.5 * dishUnitFontSize, 0.2 * dishUnitFontSize, 0.5 * dishUnitFontSize, 0.2 * dishUnitFontSize)); // количество и цена порции setStylePropertyValue("dishPortionTextStyle", "FontSize", dKoefPortionCount * dishNameFontSize); // промокод AppLib.SetPromocodeTextStyle(txtPromoCode); // яркость фона string opacity = AppLib.GetAppSetting("BackgroundImageBrightness"); if (opacity != null) { imgBackground.Opacity = opacity.ToDouble(); } // заголовок списка dishesListTitle.Margin = new Thickness(0, titleFontSize, 0, titleFontSize); dishesListTitle.FontSize = 1.5 * titleFontSize; // большие кнопки скроллинга var v = Enum.Parse(typeof(HorizontalAlignment), (string)AppLib.GetAppGlobalValue("dishesPanelScrollButtonHorizontalAlignment")); btnScrollDown.Width = (double)AppLib.GetAppGlobalValue("dishesPanelScrollButtonSize"); btnScrollDown.Height = (double)AppLib.GetAppGlobalValue("dishesPanelScrollButtonSize"); btnScrollDown.HorizontalAlignment = (HorizontalAlignment)v; btnScrollUp.Width = (double)AppLib.GetAppGlobalValue("dishesPanelScrollButtonSize"); btnScrollUp.Height = (double)AppLib.GetAppGlobalValue("dishesPanelScrollButtonSize"); btnScrollUp.HorizontalAlignment = (HorizontalAlignment)v; } // method
private FlowDocument createDocument(int width) { // создать объекты верхнего и нижнего колонтитулов XmlDocument xmlHeader = new XmlDocument(); xmlHeader.Load(AppDomain.CurrentDomain.BaseDirectory + string.Format(@"PrinterBill\Header-{0}.xml", _langId)); XmlDocument xmlFooter = new XmlDocument(); xmlFooter.Load(AppDomain.CurrentDomain.BaseDirectory + string.Format(@"PrinterBill\Footer-{0}.xml", _langId)); TextModel textHeader = new TextModel(); TextModel textFooter = new TextModel(); textHeader = DeSerialize <TextModel>(xmlHeader.OuterXml); textFooter = DeSerialize <TextModel>(xmlFooter.OuterXml); int leftMargin = getLineMargin("BillLineLeftMargin"); Thickness lineMargin = getLineMargin(); Thickness lineMarginIngr = lineMargin; lineMarginIngr.Top = getLineMargin("BillLineIngrTopMargin"); Thickness lineMarginPrice = lineMargin; lineMarginPrice.Top = getLineMargin("BillLinePriceTopMargin"); var doc = new FlowDocument(); doc.PageWidth = width; // значения по умолчанию doc.FontFamily = new FontFamily("Panton-Bold"); doc.FontWeight = FontWeights.Normal; doc.FontStyle = FontStyles.Normal; doc.FontSize = Convert.ToInt32(AppLib.GetAppGlobalValue("BillLineFontSize", 12)); // вставить изображение в заголовок addImageToDoc(textHeader, doc); // метка, если заказ С СОБОЙ if (_order.takeAway == true) { string langText = AppLib.GetLangTextFromAppProp("takeOrderOut"); langText = string.Concat(" **** ", langText.ToUpper(), " ****"); addParagraph(doc, langText, 1.5 * doc.FontSize, FontWeights.Bold, FontStyles.Normal, new Thickness(leftMargin, 20, 0, 10), TextAlignment.Center); } // добавить форматированный заголовок addSectionToDoc(textHeader, doc); // добавить строки заказа string currencyName = AppLib.GetLangTextFromAppProp("CurrencyName"); string sAppSet; decimal totalPrice = 0; string itemName, stringRow; foreach (DishItem item in _order.Dishes) { // блюдо itemName = AppLib.GetLangText(item.langNames); // c гарниром? if ((item.SelectedGarnishes != null) && (item.SelectedGarnishes.Count > 0)) { DishAdding garn = item.SelectedGarnishes[0]; string garnName = AppLib.GetLangText(garn.langNames); // 2017-02-02 Формирование полного наименования блюда с гарниром // если DishFullNameInGargnish = true, то полное имя берем из гарнира, // иначе к имени блюда добавляем имя гарнира sAppSet = AppLib.GetAppSetting("DishFullNameInGarnish"); if (sAppSet != null && sAppSet.ToBool()) { itemName = garnName; } else { itemName += " " + AppLib.GetLangTextFromAppProp("withGarnish") + " " + garnName; } } //string stringRow = itemName.Substring(0, itemName.Count() > 30 ? 30 : itemName.Count()); addParagraph(doc, itemName, doc.FontSize, doc.FontWeight, doc.FontStyle, lineMargin); // добавить ингредиенты if (item.SelectedIngredients != null) { stringRow = " + "; bool isFirst = true; foreach (DishAdding ingr in item.SelectedIngredients) { itemName = AppLib.GetLangText(ingr.langNames); stringRow += ((isFirst) ? "" : "; ") + itemName; isFirst = false; } addParagraph(doc, stringRow, 0.9 * doc.FontSize, doc.FontWeight, FontStyles.Italic, lineMarginIngr); } // стоимость блюда decimal price = item.GetPrice(); string priceString = string.Format("{0} x {1:0.00} {3} = {2:0.00} {3}", item.Count, price, item.Count * price, currencyName); addParagraph(doc, priceString, doc.FontSize, doc.FontWeight, doc.FontStyle, lineMarginPrice, TextAlignment.Right); totalPrice += item.Count * price; } // итог addTotalLine(doc, doc.FontSize, totalPrice, currencyName, leftMargin); // добавить форматированный "подвал" addSectionToDoc(textFooter, doc); // вставить изображение в "подвал" addImageToDoc(textFooter, doc); // печать штрих-кода string bcVal13 = _order.BarCodeValue + BarCodeLib.getUPCACheckDigit(_order.BarCodeValue); Image imageBarCode = BarCodeLib.GetBarcodeImage(bcVal13, (int)(1.2 * doc.PageWidth), 50); BlockUIContainer bcContainer = new BlockUIContainer() { Child = imageBarCode, Margin = new Thickness(leftMargin, 10, 0, 0) }; doc.Blocks.Add(bcContainer); // вывести значение баркода в чек //string bcDisplay = string.Format("{0} {1} {2} {3}", bcVal13.Substring(0,2), bcVal13.Substring(2, 6), bcVal13.Substring(8, 4), bcVal13.Substring(12,1)); string bcDisplay = string.Format("{0} {1} {2}", bcVal13.Substring(0, 1), bcVal13.Substring(1, 6), bcVal13.Substring(7)); addParagraph(doc, bcDisplay, 0.75 * doc.FontSize, doc.FontWeight, doc.FontStyle, new Thickness(leftMargin, 5, 0, 0), TextAlignment.Center); return(doc); }
public bool CreateBill(out string msgBoxText) { bool retVal = true; msgBoxText = null; string userErrMsgSuffix = Environment.NewLine + AppLib.GetLangTextFromAppProp("userErrMsgSuffix"); userErrMsgSuffix = userErrMsgSuffix.Replace("\\n", Environment.NewLine); AppLib.WriteLogTraceMessage("Создание пречека для заказа " + _order.OrderNumberForPrint.ToString()); // свойства заказа, созадаваемые перед печатью чека: // 1. BarCodeValue - значение штрих-кода, 12 цифр (6 - yymmdd, 2 - код источника, 4 - номер чека для печати) // 2. LanguageTypeId - язык, который был выбран при создании чека (ua/en/ru) //-------------------------------------------------- string deviceName = (string)AppLib.GetAppGlobalValue("ssdID", string.Empty); if (deviceName == string.Empty) { AppLib.WriteLogErrorMessage("В config-файле не найден элемент \"ssdID\" - идентификатор терминала самообслуживания.\n\t\tTrace: PrintBill.cs, CreateBill()"); msgBoxText = "App config error: don't find 'ssdID' element." + userErrMsgSuffix; return(false); } if (deviceName.Length > 2) { deviceName = deviceName.Substring(0, 2); } // 1. OrderNumberForPrint if (_order.OrderNumberForPrint == -1) { AppLib.WriteLogErrorMessage("Класс PrintBill. Не указан номер заказа"); msgBoxText = "App error: no order number." + userErrMsgSuffix; return(false); } // дату заказа создаем ПЕРЕД печатью _order.OrderDate = DateTime.Now; // 2. BarCodeValue // идент.устройства - 2 символа if (deviceName.Length <= 2) { deviceName = string.Format("{0:D2}", deviceName); } else { deviceName = deviceName.Substring(0, 2); } // дата заказа в формате yyMMdd - 6 символов // номер заказа (для печати - случайный) в формате 0000 - 4 символа // т.к. в формате EAN-13 если первый символ - 0, то он удаляется, используем в начале дату string sBuf = (_order.OrderDate == null) ? "000000" : string.Format("{0:yyMMdd}", _order.OrderDate); _order.BarCodeValue = sBuf + _order.OrderNumberForPrint.ToString("000000"); // 3. LanguageTypeId _order.LanguageTypeId = AppLib.AppLang; // ширина из config-файла int width = (int)AppLib.GetAppGlobalValue("BillPageWidht", 0); if (width == 0) { AppLib.WriteLogErrorMessage("В config-файле не указан элемент BillPageWidht с шириной чека. Берется значение по умолчанию - 300 (7,8см)"); width = 300; } // принтеры в системе List <PrintQueue> printers = PrintHelper.getPrintersList(); if (printers == null) { AppLib.WriteLogErrorMessage("В системе не зарегистрирован ни один принтер!!"); msgBoxText = AppLib.GetLangTextFromAppProp("printConfigError"); return(false); } else { try { string sLog = string.Join(Environment.NewLine + "\t", printers.Select(pq => pq.Name + ", status '" + getPrinterStatus(pq) + "', driver '" + pq.QueueDriver.Name + "'")); AppLib.WriteLogTraceMessage("Системные принтеры: " + Environment.NewLine + "\t" + sLog); } catch (Exception) { } } // имя принтера для печати чека string printerName = null; string result = null; #region поиск принтера для печати чека printerName = AppLib.GetAppSetting("PrinterName"); PrintQueue printer = PrintHelper.GetPrintQueueByName(printerName); if (printer == null) { AppLib.WriteLogErrorMessage("В config-файле не указан элемент PrinterName или в системе не найден принтер: " + printerName); printerName = null; } else { result = getPrinterStatus(printer); AppLib.WriteLogTraceMessage($"Принтер '{printerName}' находится в состоянии '{result}'"); } // если принтер из настроек не Ок, то берем принтер по умолчанию if ((printer == null) || ((result != null) && (result != "OK"))) { AppLib.WriteLogTraceMessage("Предпринимается попытка использовать принтер по умолчанию..."); printer = PrintHelper.GetDefaultPrinter(); if ((printer != null) && ((printerName == null) || ((printerName != null) && (printer.Name != printerName)))) { printerName = printer.Name; result = getPrinterStatus(printer); AppLib.WriteLogTraceMessage($"Найден принтер по умолчанию: {printerName}"); AppLib.WriteLogTraceMessage($"Принтер '{printerName}' находится в состоянии '{result}'"); } } // если принтер по умолчанию не ОК, то берем первый в системе if (printer == null) { AppLib.WriteLogTraceMessage("Предпринимается попытка использовать первый найденный принтер в ОС..."); printer = PrintHelper.GetFirstPrinter(); if ((printer != null) && ((printerName == null) || ((printerName != null) && (printer.Name != printerName)))) { printerName = printer.Name; result = getPrinterStatus(printer); AppLib.WriteLogTraceMessage($"Найден первый принтер: {printerName}"); AppLib.WriteLogTraceMessage($"Принтер '{printerName}' находится в состоянии '{result}'"); } } // принтер не найден - досвидос if (printer == null) { msgBoxText = "App print error: not found any printer." + userErrMsgSuffix; return(false); } // найден, но статус не ОК - досвидос else if ((result != null) && (result != "OK")) { string sFormat = AppLib.GetLangTextFromAppProp("printerStatusMsg"); if (sFormat != null) { sFormat = sFormat.Replace("\\n", Environment.NewLine); } msgBoxText = string.Format(sFormat, printerName, result) + userErrMsgSuffix; return(false); } #endregion // создание документа AppLib.WriteLogTraceMessage($" Создаю документ для печати..."); FlowDocument doc = null; try { doc = createDocument(width); AppLib.WriteLogTraceMessage($" - документ создан успешно"); } catch (Exception ex) { result = AppLib.GetLangTextFromAppProp("afterPrintingErrMsg"); if (result != null) { result = result.Replace("\\n", Environment.NewLine); } msgBoxText = result + userErrMsgSuffix; AppLib.WriteLogErrorMessage(" Ошибка формирования документа: " + ex.ToString()); return(false); } // имя задания на принтер string prnTaskName = "bill " + _order.OrderNumberForPrint.ToString(); // вывод документа на принтер AppLib.WriteLogTraceMessage($" Вывожу пречек на принтер..."); retVal = PrintHelper.PrintFlowDocument(doc, prnTaskName, printerName, out msgBoxText); if (retVal == false) { // сообщение об ошибке в лог AppLib.WriteLogErrorMessage(" Ошибка печати документа: " + msgBoxText); // и на экран пользователю result = AppLib.GetLangTextFromAppProp("afterPrintingErrMsg"); if (result != null) { result = result.Replace("\\n", Environment.NewLine); } msgBoxText = result + userErrMsgSuffix; } else { AppLib.WriteLogTraceMessage("Пречек распечатан успешно"); if (msgBoxText != null) { AppLib.WriteLogErrorMessage(msgBoxText); } } return(retVal); }
// анимировать перемещение блюда в тележку private void animateDishSelection() { // AppLib.WriteLogTraceMessage("Выбор Вока: вычисление геометрии анимации"); // перемещаемое изображение (animImage.Fill as VisualBrush).Visual = dishImage; //animImage.Fill = Brushes.Green; // debug // обновление пути анимации PathFigure pf = (animPath.Data as PathGeometry).Figures[0]; BezierSegment bezierSeg = (pf.Segments[0] as BezierSegment); // получить точку начала анимации: центр панели блюда Point fromPoint = dishImage.PointToScreen(new Point(dishImage.ActualWidth / 2d, dishImage.ActualHeight / 2d)); if (AppLib.ScreenScale != 1d) { fromPoint = PointFromScreen(fromPoint); } Point toPoint = bezierSeg.Point3; pf.StartPoint = fromPoint; // и опорные точки кривой Безье double dX, dY; Point p1, p2; if (AppLib.IsAppVerticalLayout) { dX = fromPoint.X - toPoint.X; dY = fromPoint.Y - toPoint.Y; // блюдо справа if (dX > 0) { p1 = new Point(0.5 * toPoint.X, 1.3 * fromPoint.Y); p2 = new Point(0.8 * toPoint.X, 0.5 * fromPoint.Y); } // блюдо слева else { p1 = new Point(1.2 * toPoint.X, 1.3 * fromPoint.Y); p2 = new Point(1.2 * toPoint.X, 0.5 * fromPoint.Y); } } else { dX = fromPoint.X - toPoint.X; dY = toPoint.Y - fromPoint.Y; p1 = new Point(fromPoint.X - 0.3 * dX, 0.3 * fromPoint.Y); p2 = new Point(toPoint.X + 0.05 * dX, toPoint.Y - 0.8 * dY); } bezierSeg.Point1 = p1; bezierSeg.Point2 = p2; // AppLib.WriteLogTraceMessage("Выбор Вока: сделать видимой панель анимации"); canvasAnim.Visibility = Visibility.Visible; // установить скорость анимации // AppLib.WriteLogTraceMessage("Выбор Вока: установить скорость анимации"); double animSpeed = double.Parse(AppLib.GetAppSetting("SelectDishAnimationSpeed")); // in msec TimeSpan ts = TimeSpan.FromMilliseconds(animSpeed); foreach (Timeline item in _animDishSelection.Children) { item.Duration = ts; } // обновление стоимости заказа в анимациях // AppLib.WriteLogTraceMessage("Выбор Вока: старт анимации"); _animDishSelection.Begin(); }