Skip to content

Commit dc63ba9

Browse files
authored
feat: summary of annotations in folded lines (#5117)
Currently, when there are gutter annotations for lines which are folded away, the gutter annotations are invisible. This change adds a (optional) one-line summary of the annotations in the folded code.
1 parent 3a3849b commit dc63ba9

8 files changed

+261
-94
lines changed

ace.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ export namespace Ace {
195195
hasCssTransforms: boolean;
196196
maxPixelHeight: number;
197197
useSvgGutterIcons: boolean;
198+
showFoldedAnnotations: boolean;
198199
}
199200

200201
export interface MouseHandlerOptions {

src/css/editor.css.js

+23-16
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ module.exports = `
110110
pointer-events: none;
111111
}
112112
113-
.ace_gutter-cell, .ace_gutter-cell_svg-icons {
113+
.ace_gutter-cell, .ace_gutter-cell_svg-icons {
114114
position: absolute;
115115
top: 0;
116116
left: 0;
@@ -120,18 +120,23 @@ module.exports = `
120120
background-repeat: no-repeat;
121121
}
122122
123-
.ace_gutter-cell_svg-icons .ace_icon_svg{
123+
.ace_gutter-cell_svg-icons .ace_icon_svg {
124124
margin-left: -14px;
125125
float: left;
126126
}
127127
128-
.ace_gutter-cell.ace_error, .ace_icon.ace_error {
128+
.ace_gutter-cell .ace_icon {
129+
margin-left: -18px;
130+
float: left;
131+
}
132+
133+
.ace_gutter-cell.ace_error, .ace_icon.ace_error, .ace_icon.ace_error_fold {
129134
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");
130135
background-repeat: no-repeat;
131136
background-position: 2px center;
132137
}
133138
134-
.ace_gutter-cell.ace_warning, .ace_icon.ace_warning {
139+
.ace_gutter-cell.ace_warning, .ace_icon.ace_warning, .ace_icon.ace_warning_fold {
135140
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");
136141
background-repeat: no-repeat;
137142
background-position: 2px center;
@@ -147,18 +152,27 @@ module.exports = `
147152
}
148153
149154
.ace_icon_svg.ace_error {
150-
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJyZWQiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KPGNpcmNsZSBmaWxsPSJub25lIiBjeD0iOCIgY3k9IjgiIHI9IjciIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGxpbmUgeDE9IjExIiB5MT0iNSIgeDI9IjUiIHkyPSIxMSIvPgo8bGluZSB4MT0iMTEiIHkxPSIxMSIgeDI9IjUiIHkyPSI1Ii8+CjwvZz4KPC9zdmc+");
155+
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJyZWQiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KPGNpcmNsZSBmaWxsPSJub25lIiBjeD0iOCIgY3k9IjgiIHI9IjciIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGxpbmUgeDE9IjExIiB5MT0iNSIgeDI9IjUiIHkyPSIxMSIvPgo8bGluZSB4MT0iMTEiIHkxPSIxMSIgeDI9IjUiIHkyPSI1Ii8+CjwvZz4KPC9zdmc+");
151156
background-color: crimson;
152157
}
153158
.ace_icon_svg.ace_warning {
154-
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJkYXJrb3JhbmdlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+Cjxwb2x5Z29uIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGZpbGw9Im5vbmUiIHBvaW50cz0iOCAxIDE1IDE1IDEgMTUgOCAxIi8+CjxyZWN0IHg9IjgiIHk9IjEyIiB3aWR0aD0iMC4wMSIgaGVpZ2h0PSIwLjAxIi8+CjxsaW5lIHgxPSI4IiB5MT0iNiIgeDI9IjgiIHkyPSIxMCIvPgo8L2c+Cjwvc3ZnPg==");
159+
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJkYXJrb3JhbmdlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+Cjxwb2x5Z29uIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGZpbGw9Im5vbmUiIHBvaW50cz0iOCAxIDE1IDE1IDEgMTUgOCAxIi8+CjxyZWN0IHg9IjgiIHk9IjEyIiB3aWR0aD0iMC4wMSIgaGVpZ2h0PSIwLjAxIi8+CjxsaW5lIHgxPSI4IiB5MT0iNiIgeDI9IjgiIHkyPSIxMCIvPgo8L2c+Cjwvc3ZnPg==");
155160
background-color: darkorange;
156161
}
157162
.ace_icon_svg.ace_info {
158-
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJibHVlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CjxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjgiIGN5PSI4IiByPSI3IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjxwb2x5bGluZSBwb2ludHM9IjggMTEgOCA4Ii8+Cjxwb2x5bGluZSBwb2ludHM9IjkgOCA2IDgiLz4KPGxpbmUgeDE9IjEwIiB5MT0iMTEiIHgyPSI2IiB5Mj0iMTEiLz4KPHJlY3QgeD0iOCIgeT0iNSIgd2lkdGg9IjAuMDEiIGhlaWdodD0iMC4wMSIvPgo8L2c+Cjwvc3ZnPg==");
163+
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiI+CjxnIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSJibHVlIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CjxjaXJjbGUgZmlsbD0ibm9uZSIgY3g9IjgiIGN5PSI4IiByPSI3IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjxwb2x5bGluZSBwb2ludHM9IjggMTEgOCA4Ii8+Cjxwb2x5bGluZSBwb2ludHM9IjkgOCA2IDgiLz4KPGxpbmUgeDE9IjEwIiB5MT0iMTEiIHgyPSI2IiB5Mj0iMTEiLz4KPHJlY3QgeD0iOCIgeT0iNSIgd2lkdGg9IjAuMDEiIGhlaWdodD0iMC4wMSIvPgo8L2c+Cjwvc3ZnPg==");
159164
background-color: royalblue;
160165
}
161166
167+
.ace_icon_svg.ace_error_fold {
168+
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSI+CiAgPHBhdGggZD0ibSAxOC45Mjk4NTEsNy44Mjk4MDc2IGMgMC4xNDYzNTMsNi4zMzc0NjA0IC02LjMyMzE0Nyw3Ljc3Nzg0NDQgLTcuNDc3OTEyLDcuNzc3ODQ0NCAtMi4xMDcyNzI2LC0wLjEyODc1IDUuMTE3Njc4LDAuMzU2MjQ5IDUuMDUxNjk4LC03Ljg3MDA2MTggLTAuNjA0NjcyLC04LjAwMzk3MzQ5IC03LjA3NzI3MDYsLTcuNTYzMTE4OSAtNC44NTczLC03LjQzMDM5NTU2IDEuNjA2LC0wLjExNTE0MjI1IDYuODk3NDg1LDEuMjYyNTQ1OTYgNy4yODM1MTQsNy41MjI2MTI5NiB6IiBmaWxsPSJjcmltc29uIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibSA4LjExNDc1NjIsMi4wNTI5ODI4IGMgMy4zNDkxNjk4LDAgNi4wNjQxMzI4LDIuNjc2ODYyNyA2LjA2NDEzMjgsNS45Nzg5NTMgMCwzLjMwMjExMjIgLTIuNzE0OTYzLDUuOTc4OTIwMiAtNi4wNjQxMzI4LDUuOTc4OTIwMiAtMy4zNDkxNDczLDAgLTYuMDY0MTc3MiwtMi42NzY4MDggLTYuMDY0MTc3MiwtNS45Nzg5MjAyIDAuMDA1MzksLTMuMjk5ODg2MSAyLjcxNzI2NTYsLTUuOTczNjQwOCA2LjA2NDE3NzIsLTUuOTc4OTUzIHogbSAwLC0xLjczNTgyNzE5IGMgLTQuMzIxNDgzNiwwIC03LjgyNDc0MDM4LDMuNDU0MDE4NDkgLTcuODI0NzQwMzgsNy43MTQ3ODAxOSAwLDQuMjYwNzI4MiAzLjUwMzI1Njc4LDcuNzE0NzQ1MiA3LjgyNDc0MDM4LDcuNzE0NzQ1MiA0LjMyMTQ0OTgsMCA3LjgyNDY5OTgsLTMuNDU0MDE3IDcuODI0Njk5OCwtNy43MTQ3NDUyIDAsLTIuMDQ2MDkxNCAtMC44MjQzOTIsLTQuMDA4MzY3MiAtMi4yOTE3NTYsLTUuNDU1MTc0NiBDIDEyLjE4MDIyNSwxLjEyOTk2NDggMTAuMTkwMDEzLDAuMzE3MTU1NjEgOC4xMTQ3NTYyLDAuMzE3MTU1NjEgWiBNIDYuOTM3NDU2Myw4LjI0MDU5ODUgNC42NzE4Njg1LDEwLjQ4NTg1MiA2LjAwODY4MTQsMTEuODc2NzI4IDguMzE3MDAzNSw5LjYwMDc5MTEgMTAuNjI1MzM3LDExLjg3NjcyOCAxMS45NjIxMzgsMTAuNDg1ODUyIDkuNjk2NTUwOCw4LjI0MDU5ODUgMTEuOTYyMTM4LDYuMDA2ODA2NiAxMC41NzMyNDYsNC42Mzc0MzM1IDguMzE3MDAzNSw2Ljg3MzQyOTcgNi4wNjA3NjA3LDQuNjM3NDMzNSA0LjY3MTg2ODUsNi4wMDY4MDY2IFoiIGZpbGw9ImNyaW1zb24iIHN0cm9rZS13aWR0aD0iMiIvPgo8L3N2Zz4=");
169+
background-color: crimson;
170+
}
171+
.ace_icon_svg.ace_warning_fold {
172+
-webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAyMCAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC43NzY5IDE0LjczMzdMOC42NTE5MiAyLjQ4MzY5QzguMzI5NDYgMS44Mzg3NyA3LjQwOTEzIDEuODM4NzcgNy4wODY2NyAyLjQ4MzY5TDAuOTYxNjY5IDE0LjczMzdDMC42NzA3NzUgMTUuMzE1NSAxLjA5MzgzIDE2IDEuNzQ0MjkgMTZIMTMuOTk0M0MxNC42NDQ4IDE2IDE1LjA2NzggMTUuMzE1NSAxNC43NzY5IDE0LjczMzdaTTMuMTYwMDcgMTQuMjVMNy44NjkyOSA0LjgzMTU2TDEyLjU3ODUgMTQuMjVIMy4xNjAwN1pNOC43NDQyOSAxMS42MjVWMTMuMzc1SDYuOTk0MjlWMTEuNjI1SDguNzQ0MjlaTTYuOTk0MjkgMTAuNzVWNy4yNUg4Ljc0NDI5VjEwLjc1SDYuOTk0MjlaIiBmaWxsPSIjRUM3MjExIi8+CjxwYXRoIGQ9Ik0xMS4xOTkxIDIuOTUyMzhDMTAuODgwOSAyLjMxNDY3IDEwLjM1MzcgMS44MDUyNiA5LjcwNTUgMS41MDlMMTEuMDQxIDEuMDY5NzhDMTEuNjg4MyAwLjk0OTgxNCAxMi4zMzcgMS4yNzI2MyAxMi42MzE3IDEuODYxNDFMMTcuNjEzNiAxMS44MTYxQzE4LjM1MjcgMTMuMjkyOSAxNy41OTM4IDE1LjA4MDQgMTYuMDE4IDE1LjU3NDVDMTYuNDA0NCAxNC40NTA3IDE2LjMyMzEgMTMuMjE4OCAxNS43OTI0IDEyLjE1NTVMMTEuMTk5MSAyLjk1MjM4WiIgZmlsbD0iI0VDNzIxMSIvPgo8L3N2Zz4=");
173+
background-color: darkorange;
174+
}
175+
162176
.ace_scrollbar {
163177
contain: strict;
164178
position: absolute;
@@ -452,17 +466,10 @@ module.exports = `
452466
outline: 1px solid #5E9ED6;
453467
}
454468
455-
.ace_gutter-tooltip_header {
456-
font-weight: bold;
457-
}
458-
459-
.ace_gutter-tooltip_body {
460-
padding-top: 5px;
461-
}
462-
463-
.ace_gutter-tooltip .ace_icon {
469+
.ace_icon {
464470
display: inline-block;
465471
width: 18px;
472+
vertical-align: top;
466473
}
467474
468475
.ace_icon_svg {

src/editor.js

+1
Original file line numberDiff line numberDiff line change
@@ -2932,6 +2932,7 @@ config.defineOptions(Editor.prototype, "editor", {
29322932
useTextareaForIME: "renderer",
29332933
useResizeObserver: "renderer",
29342934
useSvgGutterIcons: "renderer",
2935+
showFoldedAnnotations: "renderer",
29352936

29362937
scrollSpeed: "$mouseHandler",
29372938
dragDelay: "$mouseHandler",

src/ext/options.js

+3
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ var optionGroups = {
198198
"Use SVG gutter icons": {
199199
path: "useSvgGutterIcons"
200200
},
201+
"Annotations for folded lines": {
202+
path: "showFoldedAnnotations"
203+
},
201204
"Keyboard Accessibility Mode": {
202205
path: "enableKeyboardAccessibility"
203206
}

src/layer/gutter.js

+48-22
Original file line numberDiff line numberDiff line change
@@ -290,25 +290,9 @@ class Gutter{
290290

291291
var lineHeight = config.lineHeight + "px";
292292

293-
var className;
294-
if (this.$useSvgGutterIcons){
295-
className = "ace_gutter-cell_svg-icons ";
296-
297-
if (this.$annotations[row]){
298-
annotationNode.className = "ace_icon_svg" + this.$annotations[row].className;
299-
300-
dom.setStyle(annotationNode.style, "height", lineHeight);
301-
dom.setStyle(annotationNode.style, "display", "block");
302-
}
303-
else {
304-
dom.setStyle(annotationNode.style, "display", "none");
305-
}
306-
}
307-
else {
308-
className = "ace_gutter-cell ";
309-
dom.setStyle(annotationNode.style, "display", "none");
310-
}
311-
293+
var className = this.$useSvgGutterIcons ? "ace_gutter-cell_svg-icons " : "ace_gutter-cell ";
294+
var iconClassName = this.$useSvgGutterIcons ? "ace_icon_svg" : "ace_icon";
295+
312296
if (this.$highlightGutterLine) {
313297
if (row == this.$cursorRow || (fold && row < this.$cursorRow && row >= foldStart && this.$cursorRow <= fold.end.row)) {
314298
className += "ace_gutter-active-line ";
@@ -324,7 +308,7 @@ class Gutter{
324308
className += breakpoints[row];
325309
if (decorations[row])
326310
className += decorations[row];
327-
if (this.$annotations[row])
311+
if (this.$annotations[row] && row !== foldStart)
328312
className += this.$annotations[row].className;
329313
if (element.className != className)
330314
element.className = className;
@@ -338,8 +322,29 @@ class Gutter{
338322

339323
if (c) {
340324
var className = "ace_fold-widget ace_" + c;
341-
if (c == "start" && row == foldStart && row < fold.end.row)
325+
if (c == "start" && row == foldStart && row < fold.end.row){
342326
className += " ace_closed";
327+
var foldAnnotationClass;
328+
var annotationInFold = false;
329+
330+
for (var i = row + 1; i <= fold.end.row; i++){
331+
if (!this.$annotations[i])
332+
continue;
333+
334+
if (this.$annotations[i].className === " ace_error"){
335+
annotationInFold = true;
336+
foldAnnotationClass = " ace_error_fold";
337+
break;
338+
}
339+
if (this.$annotations[i].className === " ace_warning"){
340+
annotationInFold = true;
341+
foldAnnotationClass = " ace_warning_fold";
342+
continue;
343+
}
344+
}
345+
346+
element.className += foldAnnotationClass;
347+
}
343348
else
344349
className += " ace_open";
345350
if (foldWidget.className != className)
@@ -352,6 +357,28 @@ class Gutter{
352357
dom.setStyle(foldWidget.style, "display", "none");
353358
}
354359
}
360+
361+
if (annotationInFold && this.$showFoldedAnnotations){
362+
annotationNode.className = iconClassName;
363+
annotationNode.className += foldAnnotationClass;
364+
365+
dom.setStyle(annotationNode.style, "height", lineHeight);
366+
dom.setStyle(annotationNode.style, "display", "block");
367+
}
368+
else if (this.$annotations[row]){
369+
annotationNode.className = iconClassName;
370+
371+
if (this.$useSvgGutterIcons)
372+
annotationNode.className += this.$annotations[row].className;
373+
else
374+
element.classList.add(this.$annotations[row].className.replace(" ", ""));
375+
376+
dom.setStyle(annotationNode.style, "height", lineHeight);
377+
dom.setStyle(annotationNode.style, "display", "block");
378+
}
379+
else {
380+
dom.setStyle(annotationNode.style, "display", "none");
381+
}
355382

356383
var text = (gutterRenderer
357384
? gutterRenderer.getText(session, row)
@@ -372,7 +399,6 @@ class Gutter{
372399
this.$highlightGutterLine = highlightGutterLine;
373400
}
374401

375-
376402
setShowLineNumbers(show) {
377403
this.$renderer = !show && {
378404
getWidth: function() {return 0;},

0 commit comments

Comments
 (0)