@@ -28,9 +28,11 @@ Control {
2828
2929 property string iconSource
3030 property bool dndEnabled: false
31+ property bool isDragHover: false
3132 readonly property bool isWindowedMode: LauncherController .currentFrame === " WindowedFrame"
3233 property alias displayFont: iconItemLabel .font
3334 property real iconScaleFactor: 1.0
35+ property bool iconIntroAnimRunning: false
3436
3537 Accessible .name : iconItemLabel .text
3638
@@ -53,6 +55,7 @@ Control {
5355 }
5456
5557 contentItem: Button {
58+ hoverEnabled: ! root .iconIntroAnimRunning
5659 focusPolicy: Qt .NoFocus
5760 ColorSelector .pressed : false
5861 ColorSelector .family : D .Palette .CrystalColor
@@ -67,10 +70,42 @@ Control {
6770 }
6871
6972 Item {
73+ id: iconContainer
7074 width: parent .width / 2
7175 height: width
7276 anchors .horizontalCenter : parent .horizontalCenter
7377
78+ Rectangle {
79+ id: dragAndfolderBackground
80+ visible: root .icons !== undefined || (root .isDragHover && ! isWindowedMode)
81+ opacity: root .icons !== undefined || (root .isDragHover && ! isWindowedMode) ? 1 : 0
82+ scale: (root .isDragHover && ! isWindowedMode) ? 1.2 : 1
83+ color: " #26FFFFFF"
84+ Behavior on opacity {
85+ NumberAnimation { duration: 200 ; easing .type : Easing .OutQuad }
86+ }
87+ Behavior on scale {
88+ NumberAnimation { duration: 200 ; easing .type : Easing .OutCubic }
89+ }
90+ anchors .fill : parent
91+ radius: 12
92+
93+ NumberAnimation on scale {
94+ id: ininAni
95+ running: false
96+ from: 1.2
97+ to: 1
98+ duration: 200
99+ easing .type : Easing .OutCubic
100+ }
101+
102+ Component .onCompleted : {
103+ if (root .icons !== undefined && dndItem .mergeAnimTargetIcon && dndItem .mergeAnimTargetIcon2 ) {
104+ ininAni .start ()
105+ }
106+ }
107+ }
108+
74109 Loader {
75110 id: iconLoader
76111 anchors .fill : parent
@@ -91,8 +126,10 @@ Control {
91126 // Item will be hidden by checking the dndItem.currentlyDraggedId property. We assign the value
92127 // to that property here
93128 dndItem .currentlyDraggedId = target .Drag .mimeData [" text/x-dde-launcher-dnd-desktopId" ]
129+ dndItem .currentlyDraggedIconName = root .iconSource
94130 dndItem .Drag .hotSpot = target .Drag .hotSpot
95131 dndItem .Drag .mimeData = target .Drag .mimeData
132+ dndItem .mergeSize = Math .min (iconLoader .width , iconLoader .height )
96133
97134 iconLoader .grabToImage (function (result ) {
98135 dndItem .Drag .imageSource = result .url ;
@@ -118,50 +155,120 @@ Control {
118155 Component {
119156 id: folderComponent
120157
121- Rectangle {
158+ Item {
159+ id: iconItem
122160 anchors .fill : parent
123- color: " #26FFFFFF"
124- radius: 12
125-
126- GridLayout {
127- id: folderGrid
128- anchors .fill : parent
129- rows: 2
130- columns: 2
131- anchors .margins : 8
132- columnSpacing: 8
133- rowSpacing: 8
134-
135- Repeater {
136- model: icons
137-
138- DciIcon {
139- Layout .fillHeight : true
140- Layout .fillWidth : true
141- Layout .alignment : Qt .AlignTop | Qt .AlignLeft
142-
143- // 添加最大高度限制,确保图标高度一致
144- Layout .maximumHeight : Math .max (0 , parent .height / 2 - folderGrid .rowSpacing / 2 )
145-
146- name: modelData
147- sourceSize: Qt .size (root .maxIconSizeInFolder , root .maxIconSizeInFolder )
148- scale: (parent .width / 2 / root .maxIconSizeInFolder ) * root .iconScaleFactor
149- palette: DTK .makeIconPalette (root .palette )
150- theme: ApplicationHelper .DarkType
161+ property real maxIconCount: 2
162+ property real spacing: 8
163+ property real itemWidth: (width - ((maxIconCount + 1 ) * spacing)) / 2
164+ property real itemHeight: (height - ((maxIconCount + 1 ) * spacing)) / maxIconCount
165+
166+ function getItemX (index ) {
167+ let col = index % maxIconCount
168+ let ItemX = (col + 1 ) * spacing + col * itemWidth
169+
170+ return ItemX
171+ }
172+
173+ function getItemY (index ) {
174+ let row = Math .floor (index / maxIconCount)
175+ let ItemY = (row + 1 ) * spacing + row * itemHeight
176+ return ItemY
177+ }
178+ Repeater {
179+ model: icons
180+
181+ DciIcon {
182+ id: folderIcon
183+ x: iconItem .getItemX (index)
184+ y: iconItem .getItemY (index)
185+
186+ width: iconItem .itemWidth
187+ height: iconItem .itemHeight
188+
189+ name: modelData
190+ sourceSize: Qt .size (root .maxIconSizeInFolder , root .maxIconSizeInFolder )
191+ scale: (itemWidth / root .maxIconSizeInFolder ) * root .iconScaleFactor
192+
193+ property real introScale: 1.0
194+
195+ palette: DTK .makeIconPalette (root .palette )
196+ theme: ApplicationHelper .DarkType
197+
198+ // 位移动画属性
199+ property real iconCenterX: 0
200+ property real iconCenterY: 0
201+ ParallelAnimation {
202+ id: iconIntroAnim
203+ onStarted: root .iconIntroAnimRunning = true
204+
205+ NumberAnimation {
206+ target: folderIcon
207+ property: " scale"
208+ from: folderIcon .introScale
209+ to: (itemWidth / root .maxIconSizeInFolder ) * root .iconScaleFactor
210+ duration: 400
211+ easing .type : Easing .OutExpo
212+ }
213+ NumberAnimation {
214+ target: folderIcon
215+ property: " x"
216+ from: folderIcon .iconCenterX ; to: iconItem .getItemX (index)
217+ duration: 400
218+ easing .type : Easing .OutExpo
219+ }
220+ NumberAnimation {
221+ target: folderIcon
222+ property: " y"
223+ from: folderIcon .iconCenterY ; to: iconItem .getItemY (index)
224+ duration: 400
225+ easing .type : Easing .OutExpo
226+ }
227+
228+ onFinished: {
229+ root .iconIntroAnimRunning = false
230+ dndItem .mergeAnimPending = false
231+ dndItem .mergeAnimTargetIcon = " "
232+ dndItem .mergeAnimTargetIcon2 = " "
233+ }
234+ }
235+
236+ Component .onCompleted : {
237+ if (dndItem .mergeAnimPending
238+ && modelData === dndItem .mergeAnimTargetIcon ) {
239+ folderIcon .visible = false
240+ Qt .callLater (function () {
241+ let localPos = iconItem .mapFromItem (null ,
242+ dndItem .mergeAnimStartX , dndItem .mergeAnimStartY )
243+ folderIcon .iconCenterX = localPos .x - folderIcon .width / 2
244+ folderIcon .iconCenterY = localPos .y - folderIcon .height / 2
245+ folderIcon .introScale = (iconContainer .width / root .maxIconSizeInFolder ) * root .iconScaleFactor
246+ folderIcon .visible = true
247+ iconIntroAnim .start ()
248+ })
249+ } else if (dndItem .mergeAnimPending
250+ && modelData === dndItem .mergeAnimTargetIcon2 ) {
251+ Qt .callLater (function () {
252+ folderIcon .iconCenterX = iconContainer .width / 2 - folderIcon .width / 2
253+ folderIcon .iconCenterY = iconContainer .height / 2 - folderIcon .height / 2
254+ folderIcon .introScale = (iconContainer .width / root .maxIconSizeInFolder ) * root .iconScaleFactor
255+ iconIntroAnim .start ()
256+ })
257+ }
151258 }
152259 }
260+ }
153261
154- Repeater {
155- model: 4 - icons .length
262+ Repeater {
263+ model: 4 - icons .length
156264
157- Item {
158- Layout .fillHeight : true
159- Layout .fillWidth : true
160- Layout .alignment : Qt .AlignTop | Qt .AlignLeft
265+ Item {
266+ Layout .fillHeight : true
267+ Layout .fillWidth : true
268+ Layout .alignment : Qt .AlignTop | Qt .AlignLeft
161269
162- width: parent .width / 2
163- height: parent .height / 2
164- }
270+ width: parent .width / 2
271+ height: parent .height / 2
165272 }
166273 }
167274 }
@@ -175,7 +282,7 @@ Control {
175282 anchors .fill : parent
176283 name: iconSource
177284 sourceSize: Qt .size (root .maxIconSize , root .maxIconSize )
178- scale: (parent .width / root .maxIconSize ) * root .iconScaleFactor
285+ scale: (iconContainer .width / root .maxIconSize ) * root .iconScaleFactor
179286 palette: DTK .makeIconPalette (root .palette )
180287 theme: ApplicationHelper .DarkType
181288 fillMode: Image .PreserveAspectFit
@@ -193,6 +300,7 @@ Control {
193300 property bool singleRow: font .pixelSize > (isWindowedMode ? Helper .windowed .doubleRowMaxFontSize : Helper .fullscreen .doubleRowMaxFontSize )
194301 property bool isNewlyInstalled: model .lastLaunchedTime === 0 && model .installedTime !== 0
195302 id: iconItemLabel
303+ visible: ! root .isDragHover
196304 text: isNewlyInstalled ? (" <font color='#669DFF' size='1' style='text-shadow: 0 0 1px rgba(255,255,255,0.1)'>●</font> " + root .text ) : root .text
197305 textFormat: isNewlyInstalled ? Text .StyledText : Text .PlainText
198306 width: parent .width
0 commit comments