• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/list/list_content_modifier.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components_ng/base/modifier.h"
20 #include "core/components_ng/render/divider_painter.h"
21 #include "core/components_ng/render/drawing.h"
22 
23 namespace OHOS::Ace::NG {
ListContentModifier(const OffsetF & clipOffset,const SizeF & clipSize)24 ListContentModifier::ListContentModifier(const OffsetF& clipOffset, const SizeF& clipSize)
25 {
26     clipOffset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(clipOffset);
27     clipSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(clipSize);
28     clip_ = AceType::MakeRefPtr<PropertyBool>(true);
29     flushDivider_ = AceType::MakeRefPtr<PropertyBool>(true);
30 
31     AttachProperty(clipOffset_);
32     AttachProperty(clipSize_);
33     AttachProperty(clip_);
34     AttachProperty(flushDivider_);
35 }
36 
onDraw(DrawingContext & context)37 void ListContentModifier::onDraw(DrawingContext& context)
38 {
39     if (clip_->Get()) {
40         auto offset = clipOffset_->Get();
41         auto size = clipSize_->Get();
42         auto clipRect = RSRect(offset.GetX(), offset.GetY(),
43             offset.GetX() + size.Width(), offset.GetY() + size.Height());
44         context.canvas.ClipRect(clipRect, RSClipOp::INTERSECT);
45     }
46     if (dividerInfo_.has_value()) {
47         PaintDivider(dividerInfo_.value(), itemPosition_, context.canvas);
48     }
49 }
50 
PaintDivider(const DividerInfo & dividerInfo,const PositionMap & itemPosition,RSCanvas & canvas)51 void ListContentModifier::PaintDivider(
52     const DividerInfo& dividerInfo, const PositionMap& itemPosition, RSCanvas& canvas)
53 {
54     float fSpacingTotal = (dividerInfo.lanes - 1) * dividerInfo.laneGutter;
55     float laneLen =
56         (dividerInfo.crossSize - fSpacingTotal) / dividerInfo.lanes - dividerInfo.startMargin - dividerInfo.endMargin;
57     float crossLen = dividerInfo.crossSize - dividerInfo.startMargin - dividerInfo.endMargin;
58     DividerPainter dividerPainter(
59         dividerInfo.constrainStrokeWidth, crossLen, dividerInfo.isVertical, dividerInfo.color, LineCap::SQUARE);
60 
61     int32_t lanes = dividerInfo.lanes;
62     int32_t laneIdx = 0;
63     bool lastIsItemGroup = false;
64     bool isFirstItem = (itemPosition.begin()->first == 0);
65     std::list<int32_t> lastLineIndex;
66 
67     for (const auto& child : itemPosition) {
68         if (!isFirstItem) {
69             float divOffset = (dividerInfo.space + dividerInfo.constrainStrokeWidth) / 2; /* 2 half */
70             float mainPos = child.second.startPos - divOffset + dividerInfo.mainPadding;
71             float crossPos = dividerInfo.startMargin + dividerInfo.crossPadding;
72             if (lanes > 1 && !lastIsItemGroup && !child.second.isGroup) {
73                 crossPos +=
74                     laneIdx * ((dividerInfo.crossSize - fSpacingTotal) / dividerInfo.lanes + dividerInfo.laneGutter);
75                 dividerPainter.SetDividerLength(laneLen);
76             } else {
77                 dividerPainter.SetDividerLength(crossLen);
78             }
79             OffsetF offset = dividerInfo.isVertical ? OffsetF(mainPos, crossPos) : OffsetF(crossPos, mainPos);
80             if (dividerPainter.GetDividerLength() > 0) {
81                 dividerPainter.DrawLine(canvas, offset);
82             }
83         }
84         if (laneIdx == 0 || child.second.isGroup) {
85             lastLineIndex.clear();
86         }
87         lastLineIndex.emplace_back(child.first);
88         lastIsItemGroup = child.second.isGroup;
89         laneIdx = (lanes <= 1 || (laneIdx + 1) >= lanes || child.second.isGroup) ? 0 : laneIdx + 1;
90         isFirstItem = isFirstItem ? laneIdx > 0 : false;
91     }
92     if (!lastLineIndex.empty() && *lastLineIndex.rbegin() < dividerInfo.totalItemCount - 1) {
93         int32_t laneIdx = 0;
94         for (auto index : lastLineIndex) {
95             if (index + lanes >= dividerInfo.totalItemCount) {
96                 break;
97             }
98             float divOffset = (dividerInfo.space - dividerInfo.constrainStrokeWidth) / 2; /* 2 half */
99             float mainPos = itemPosition.at(index).endPos + divOffset + dividerInfo.mainPadding;
100             float crossPos = dividerInfo.startMargin + dividerInfo.crossPadding;
101             if (lanes > 1 && !itemPosition.at(index).isGroup) {
102                 crossPos +=
103                     laneIdx * ((dividerInfo.crossSize - fSpacingTotal) / dividerInfo.lanes + dividerInfo.laneGutter);
104                 dividerPainter.SetDividerLength(laneLen);
105             } else {
106                 dividerPainter.SetDividerLength(crossLen);
107             }
108             OffsetF offset = dividerInfo.isVertical ? OffsetF(mainPos, crossPos) : OffsetF(crossPos, mainPos);
109             if (dividerPainter.GetDividerLength() > 0) {
110                 dividerPainter.DrawLine(canvas, offset);
111             }
112             laneIdx++;
113         }
114     }
115 }
116 } // namespace OHOS::Ace::NG
117