public void ResetMaxDishesCountOnPage() { // создать элемент заказа (блюдо) OrderDishViewModel dishModel = new OrderDishViewModel(); dishModel.DishName = "QWERTY"; dishModel.Quantity = 1; // создать панель элемента DishPanel dshPnl = new DishPanel(dishModel, _colWidth); // вычислить его высоту _canvas.Children.Add(dshPnl); double h = 0d; #if fromActualHeight dshPnl.UpdateLayout(); h = dshPnl.ActualHeight; #else dshPnl.Measure(_sizeMeasure); h = dshPnl.DesiredSize.Height; #endif _canvas.Children.Clear(); // вычислить кол-во элементов на странице, округлить до ближайшего наибольшего if (h > 0d) { _maxDishesCountOnPage = Convert.ToInt32(Math.Ceiling((_pageColsCount * _colHeight) / h)); AppLib.WriteLogTraceMessage(" - reset order items count to {0}", _maxDishesCountOnPage.ToString()); } else { AppLib.WriteLogErrorMessage(" - error while measure dish panel, dish height = 0!!!"); } }
// для удаляемого блюда (при переносе в следующую колонку), создать массив UI-элементов, которые будут // переноситься в следующую колонку для предотвращения "висячих" разделителей номера подачи и ингредиентов internal UIElement[] RemoveDish(DishPanel dishPanel, double topValue, double cnvHeight) { int idx = stkDishes.Children.IndexOf(dishPanel); double totalHeight = topValue + this.DesiredSize.Height; List <UIElement> retVal = new List <UIElement>(); retVal.Add(dishPanel); this.stkDishes.Children.Remove(dishPanel); totalHeight -= dishPanel.DesiredSize.Height; // если не пусто, то это ингредиент и содержит значение родительского Uid string parentUid = dishPanel.DishView.ParentUID; UIElement uiElem; bool isMove; // сохраняем в массиве разделитель подач или все ингредиенты вместе с блюдом for (int i = idx - 1; i >= 0; i--) { uiElem = stkDishes.Children[i]; // условия переноса строки заказа в следующий столбец // - это разделитель (номер подачи) isMove = ((uiElem is DishDelimeterPanel) && ((DishDelimeterPanel)uiElem).DontTearOffNext); // - или это блюдо для переносимого ингредиента if ((!isMove) && (uiElem is DishPanel) && !parentUid.IsNull()) { DishPanel dsPnl = (uiElem as DishPanel); isMove = (dsPnl.DishView.UID == parentUid) && dsPnl.DishView.ParentUID.IsNull(); // признак блюда //((uiElem as DishPanel).DishView.ParentUID == parentUid))) } // - или выходим за рамки по вертикали if (!isMove && (Math.Ceiling(totalHeight) >= cnvHeight)) { isMove = true; } if (isMove) { retVal.Add(uiElem); this.stkDishes.Children.Remove(uiElem); totalHeight -= uiElem.DesiredSize.Height; } else { break; } } if (retVal.Count > 1) { retVal.Reverse(); } return(retVal.ToArray()); }
private OrderPanel createOrderPanel(OrderViewModel orderModel, int dishIdxFrom, int dishIdxTo, bool isTailSplit) { if (dishIdxFrom > dishIdxTo) { return(null); } OrderPanel ordPanel = new OrderPanel(orderModel, 0, _colWidth, (dishIdxFrom == 0 ? true: false)); // не с первого блюда - добавляем разделитель продолжения на предыд.странице if (dishIdxFrom != 0) { ordPanel.AddDelimiter(createContinuePanel(false)); } OrderDishViewModel dishModel; int curFiling = 0; for (int i = dishIdxFrom; i <= dishIdxTo; i++) { dishModel = orderModel.Dishes[i]; // разделитель подач if (curFiling != dishModel.FilingNumber) { curFiling = dishModel.FilingNumber; DishDelimeterPanel newDelimPanel = createFilingPanel(curFiling); ordPanel.AddDelimiter(newDelimPanel); } // панель блюда DishPanel dishPanel = new DishPanel(dishModel, _colWidth); ordPanel.AddDish(dishPanel); } // оторванных хвост (dishIdxTo меньше кол-ва элементов) - добавляем разделитель продолжения на след.странице if (isTailSplit) { ordPanel.AddDelimiter(createContinuePanel(true)); } return(ordPanel); }
// добавить блюдо в панель заказа и измерить высоту строки блюда public void AddDish(DishPanel dishPanel) { this.stkDishes.Children.Add(dishPanel); }
// возвращает следующий/предыдущий блок элементов панели заказа // блок элементов - это блюдо с предварительным разделителем подач (точнее панель-разделитель, у которой свойство DontTearOffNext = true), // или блюдо с ингредиентами, // или заголовок заказа с несколькими первыми элементами (не менее 2-х) // или два ингредиента // isDetachItems == true - блоки отсоединяются от панели // forceForward - принудительный просмотр вперед, иначе направление движения зависит от _shiftForward private List <FrameworkElement> getNextItemsBlock(OrderPanel orderPanel, bool isDetachItems, bool forceForward = false) { List <FrameworkElement> retVal = new List <FrameworkElement>(); bool addToBlock, endBlock = false; int dishesCount = 0, delimCount = 0, ingrCount = 0; // счетчики элементов блока bool isForward = (forceForward) ? true : _shiftForward; int i = ((isForward) ? 0 : orderPanel.ItemsCount - 1); FrameworkElement uiElem; while ((isDetachItems) ? orderPanel.ItemsCount > 0 : i < orderPanel.DishPanels.Count) { // в режиме отсоединения элементов берем граничный элемент if (isDetachItems) { i = ((isForward) ? 0 : orderPanel.ItemsCount - 1); } uiElem = (FrameworkElement)orderPanel.DishPanels[i]; // иначе увеличиваем индекс элемента if (!isDetachItems) { ++i; } addToBlock = true; // признак включения элемента в блок // разделитель if (uiElem is DishDelimeterPanel) { if (((DishDelimeterPanel)uiElem).DontTearOffNext) // не отрывать от следующего { // считаем только неотрываемые разделители delimCount++; // при прямом проходе неотрываемый разделитель может быть только один if (isForward) { if (delimCount > 1) { addToBlock = false; endBlock = true; } // не добавлять и выйти } // при обратном проходе else { endBlock = true; // добавить и выйти } } // отрываемый разделитель, поведение, как у блюда, но без ингредиентов, поэтому он может быть только один // как в прямом, так и в обратном направлениях else { endBlock = true; } } // блюдо else if (uiElem is DishPanel) { DishPanel dsPnl = (uiElem as DishPanel); // блюдо if (dsPnl.DishView.ParentUID.IsNull()) { dishesCount++; // при прямом проходе блюдо может быть только одно if (isForward) { // уже был ингредиент или блюдо - не добавлять и выйти if ((ingrCount > 0) || (dishesCount > 1)) { addToBlock = false; endBlock = true; } } // при обратном проходе перед блюдом может быть разделитель подач else { // не добавлять и выйти if (dishesCount > 1) { addToBlock = false; endBlock = true; } } } // ингредиент, из ингредиентов делаем блоки по 2 элемента, если перед ними не было блюда else { if (isForward) { ingrCount++; // не добавлять больше 2-х ингредиентов if (ingrCount > 2) { addToBlock = false; endBlock = true; } } else { if (dishesCount == 0) { ingrCount++; // не добавлять больше 2-х ингредиентов if (ingrCount > 2) { addToBlock = false; endBlock = true; } } else // не добавлять и выйти { addToBlock = false; endBlock = true; } } } } if (addToBlock) { retVal.Add(uiElem); // и отсоединить от панели заказа if (isDetachItems) { orderPanel.DetachDish(uiElem); } } if (endBlock) { break; } } // for next if (retVal.Count == 0) { retVal = null; } return(retVal); }
//******************************************* // РАЗМЕЩЕНИЕ ПАНЕЛЕЙ ЗАКАЗОВ //******************************************* public void AddOrderPanel(OrderViewModel orderModel) { OrderPanel ordPnl; DishPanel dshPnl; //, curDshPnl = null; // СОЗДАТЬ ПАНЕЛЬ ЗАКАЗА вместе с ЗАГОЛОВКОМ заказа и строкой заголовка таблицы блюд ordPnl = new OrderPanel(orderModel, _currentPageIndex, _colWidth, true); // поле между заказами по вертикали if (_curTopValue > 0d) { _curTopValue += _hdrTopMargin; } ordPnl.SetPosition(_curTopValue, getLeftOrdPnl()); CurrentPage.AddOrder(ordPnl); CurrentPage.UpdateLayout(); // перенос в новый столбец всего заказа if ((_curTopValue + ordPnl.PanelHeight) >= _uiPanelSize.Height) { moveToNewCol(ordPnl); CurrentPage.UpdateLayout(); } int curFiling = 0; // блюда foreach (OrderDishViewModel dishModel in orderModel.Dishes) { if (curFiling != dishModel.FilingNumber) { curFiling = dishModel.FilingNumber; Brush foreground = (curFiling == 1) ? Brushes.Red : Brushes.Blue; DishDelimeterPanel newDelimPanel = new DishDelimeterPanel(_colWidth, foreground, Brushes.AliceBlue, "Подача " + curFiling.ToString()) { DontTearOffNext = true }; ordPnl.AddDelimiter(newDelimPanel); // и добавить в стек } //if (dishModel.ParentUID.IsNull()) curDshPnl = null; // сохранить родительское блюдо dshPnl = new DishPanel(dishModel, _colWidth); // , curDshPnl //if (dishModel.ParentUID.IsNull()) curDshPnl = dshPnl; // сохранить родительское блюдо // добавить строку заказа в стек ordPnl.AddDish(dshPnl); CurrentPage.UpdateLayout(); if ((_curTopValue + Math.Ceiling(ordPnl.PanelHeight)) > _uiPanelSize.Height) // переход в новый столбец { // 1. удалить из ordPnl только что добавленное блюдо // и вернуть массив удаленных элементов, возможно с "висячим" разделителем номера подачи UIElement[] delItems = ordPnl.RemoveDish(dshPnl, _curTopValue, _uiPanelSize.Height); // разбиваем блюда заказа по колонкам на той же странице if ((ordPnl.ItemsCount > 2) && ((_curColIndex < _pageColsCount) || ((_curColIndex == _pageColsCount) && (Convert.ToDouble(ordPnl.GetValue(Canvas.TopProperty)) == 0d)))) { setNextColumn(); // 2. создать новый OrderPanel для текущего блюда с заголовком таблицы ordPnl = new OrderPanel(orderModel, _currentPageIndex, _colWidth, false); // 3. добавить только что удаленные блюда ordPnl.AddDishes(delItems); // 4. привязать к канве ordPnl.SetPosition(_curTopValue, getLeftOrdPnl()); CurrentPage.AddOrder(ordPnl); } // не разбиваем заказ, а полностью переносим в новую колонку else { // 2. изменить координаты панели заказа moveToNewCol(ordPnl); // 3. добавить только что удаленные блюда ordPnl.AddDishes(delItems); } CurrentPage.UpdateLayout(); } } // foreach dishes _curTopValue += ordPnl.PanelHeight; }