private void setLastPanelPosition(OrderPanel curPanel, double panelHeight = 0d) { // при смещении назад, curTopValue указывает на Bottom панели if (!_shiftForward) { curTopValue -= ((panelHeight == 0d) ? curPanel.PanelHeight : panelHeight); } setPanelLeftTop(curPanel); // при движение вперед, сместить Top на величину _hdrTopMargin if (_shiftForward) { curTopValue += ((panelHeight == 0d) ? curPanel.PanelHeight : panelHeight); curTopValue += _hdrTopMargin; if (curTopValue > _colHeight) { curColIndex++; curTopValue = 0d; // выход за последнюю колонку if (curColIndex > _pageColsCount) { curColIndex = 1; _pageBreak = true; } } } // при движение назад else { curTopValue -= _hdrTopMargin; if (curTopValue <= 0d) { curColIndex--; curTopValue = _colHeight; } // выход за первую колонку if (curColIndex <= 0) { if ((double)curPanel.GetValue(Canvas.TopProperty) != 0d) { curPanel.SetValue(Canvas.TopProperty, 0d); } // curTopValue уже равно _colHeight; curColIndex = _pageColsCount; _pageBreak = true; } } }
// возвращает признак повторного размещения при движении назад: // много свободного места на панели временного размещения _canvas internal bool NeedRelayout() { // нет панелей - выход if (this.OrderPanels.Count == 0) { return(false); } UIElement panel1 = this.OrderPanels[0]; int panel1ColIndex = ((OrderPanel)panel1).CanvasColumnIndex; // только одна панель заказа и она в первой колонке - не переразмещаем if ((this.OrderPanels.Count == 1) && (panel1ColIndex == 1)) { if ((double)panel1.GetValue(Canvas.TopProperty) != 0d) { panel1.SetValue(Canvas.TopProperty, 0d); } return(false); } // а если первая панель не в первой колонке, то переразмещаем if (panel1ColIndex != 1) { return(true); } // перед первой панелью есть пустое место else if ((double)((OrderPanel)panel1).GetValue(Canvas.TopProperty) != 0d) { return(true); } bool retVal = false; // несколько панелей - цикл по панелям на странице // признак переразмещения: // 1. свободное место по вертикали между соседними панелями в одной колонке // больше (или в два раза меньше, 2017-12-21) _hdrTopMargin // 2. если панели одного заказа и следующая панель начинается со следующей колонки (или Top==0) и блок из следующей панели можно разместить в свободном месте в конце предыдущей колонки OrderPanel prePanel, nextPanel = (OrderPanel)_canvas.Children[0]; double prePanelTop, prePanelHeight, nextPanelTop, freeSpace, h1; for (int i = 1; i < _canvas.Children.Count; i++) { // две соседние панели prePanel = nextPanel; nextPanel = (OrderPanel)_canvas.Children[i]; prePanelTop = (double)prePanel.GetValue(Canvas.TopProperty); prePanelHeight = prePanel.PanelHeight; // в одной колонке, проверяем расстояние между панелями по вертикали if (prePanel.CanvasColumnIndex == nextPanel.CanvasColumnIndex) { nextPanelTop = (double)nextPanel.GetValue(Canvas.TopProperty); freeSpace = nextPanelTop - (prePanelTop + prePanelHeight); if (freeSpace > _hdrTopMargin) { retVal = true; break; } if (freeSpace < (_hdrTopMargin / 2.0d)) { retVal = true; break; } } // проверка на пустую колонку else if ((nextPanel.CanvasColumnIndex - prePanel.CanvasColumnIndex) > 1) { retVal = true; break; } // разные колонки else { // nextPanel - это первая панель следующей колонки, ее Top должен быть = 0 nextPanelTop = (double)nextPanel.GetValue(Canvas.TopProperty); if (nextPanelTop != 0d) { retVal = true; break; } // если панель в след.колонке - это продолжение предыд.панели, // то проверяем может ли в свободное место после предыд.панели поместиться // первый блок элементов след.панели if (nextPanel.OrderViewModel == prePanel.OrderViewModel) { freeSpace = _colHeight - (prePanelTop + prePanelHeight); // высота первого блока следующей панели List <FrameworkElement> firstBlock = getNextItemsBlock(nextPanel, false, true); h1 = getBlockHeight(firstBlock); if (h1 <= freeSpace) { retVal = true; break; } } } } 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; }