Skip to content

Commit 429a579

Browse files
Denis Zaichenkofaogustavo
authored andcommitted
[JEWEL-941] Reducing space used by images on markdown image error
- When the line contains only images, replaced the Text component with FlowRow - Using a flow row we can skip the Paragraph component that was taking extra space
1 parent 31366c3 commit 429a579

File tree

6 files changed

+159
-52
lines changed

6 files changed

+159
-52
lines changed

platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package org.jetbrains.jewel.markdown.rendering
33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.border
55
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
67
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.FlowRow
79
import androidx.compose.foundation.layout.Row
810
import androidx.compose.foundation.layout.Spacer
911
import androidx.compose.foundation.layout.fillMaxWidth
1012
import androidx.compose.foundation.layout.height
1113
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
1215
import androidx.compose.foundation.layout.width
1316
import androidx.compose.foundation.layout.widthIn
1417
import androidx.compose.foundation.text.InlineTextContent
@@ -29,6 +32,7 @@ import androidx.compose.ui.graphics.isSpecified
2932
import androidx.compose.ui.graphics.takeOrElse
3033
import androidx.compose.ui.input.pointer.PointerIcon
3134
import androidx.compose.ui.input.pointer.pointerHoverIcon
35+
import androidx.compose.ui.platform.LocalDensity
3236
import androidx.compose.ui.text.AnnotatedString
3337
import androidx.compose.ui.text.TextLayoutResult
3438
import androidx.compose.ui.text.TextStyle
@@ -193,23 +197,30 @@ public open class DefaultMarkdownBlockRenderer(
193197
softWrap: Boolean,
194198
maxLines: Int,
195199
) {
196-
val renderedContent = rememberRenderedContent(block, styling.inlinesStyling, enabled, onUrlClick)
197-
val textColor =
198-
styling.inlinesStyling.textStyle.color
199-
.takeOrElse { LocalContentColor.current }
200-
.takeOrElse { styling.inlinesStyling.textStyle.color }
201-
val mergedStyle = styling.inlinesStyling.textStyle.merge(TextStyle(color = textColor))
200+
val onlyImages = remember(block) { block.inlineContent.all { it is InlineMarkdown.Image } }
201+
val images = renderedImages(block)
202202

203-
Text(
204-
modifier = modifier,
205-
text = renderedContent,
206-
overflow = overflow,
207-
softWrap = softWrap,
208-
maxLines = maxLines,
209-
onTextLayout = onTextLayout,
210-
inlineContent = renderedImages(block),
211-
style = mergedStyle,
212-
)
203+
if (onlyImages) {
204+
RenderImages(images, modifier)
205+
} else {
206+
val renderedContent = rememberRenderedContent(block, styling.inlinesStyling, enabled, onUrlClick)
207+
val textColor =
208+
styling.inlinesStyling.textStyle.color
209+
.takeOrElse { LocalContentColor.current }
210+
.takeOrElse { styling.inlinesStyling.textStyle.color }
211+
val mergedStyle = styling.inlinesStyling.textStyle.merge(TextStyle(color = textColor))
212+
213+
Text(
214+
modifier = modifier,
215+
text = renderedContent,
216+
overflow = overflow,
217+
softWrap = softWrap,
218+
maxLines = maxLines,
219+
onTextLayout = onTextLayout,
220+
inlineContent = images,
221+
style = mergedStyle,
222+
)
223+
}
213224
}
214225

215226
@Composable
@@ -263,19 +274,27 @@ public open class DefaultMarkdownBlockRenderer(
263274
onUrlClick: (String) -> Unit,
264275
modifier: Modifier,
265276
) {
266-
val renderedContent = rememberRenderedContent(block, styling.inlinesStyling, enabled, onUrlClick)
277+
val onlyImages = remember(block) { block.inlineContent.all { it is InlineMarkdown.Image } }
278+
val images = renderedImages(block)
279+
267280
Column(modifier = modifier.padding(styling.padding)) {
268-
val textColor =
269-
styling.inlinesStyling.textStyle.color.takeOrElse {
270-
LocalContentColor.current.takeOrElse { styling.inlinesStyling.textStyle.color }
271-
}
272-
val mergedStyle = styling.inlinesStyling.textStyle.merge(TextStyle(color = textColor))
273-
Text(
274-
text = renderedContent,
275-
style = mergedStyle,
276-
modifier = Modifier.focusProperties { this.canFocus = false },
277-
inlineContent = this@DefaultMarkdownBlockRenderer.renderedImages(block),
278-
)
281+
if (onlyImages) {
282+
RenderImages(images)
283+
} else {
284+
val renderedContent = rememberRenderedContent(block, styling.inlinesStyling, enabled, onUrlClick)
285+
286+
val textColor =
287+
styling.inlinesStyling.textStyle.color.takeOrElse {
288+
LocalContentColor.current.takeOrElse { styling.inlinesStyling.textStyle.color }
289+
}
290+
val mergedStyle = styling.inlinesStyling.textStyle.merge(TextStyle(color = textColor))
291+
Text(
292+
text = renderedContent,
293+
style = mergedStyle,
294+
modifier = Modifier.focusProperties { this.canFocus = false },
295+
inlineContent = images,
296+
)
297+
}
279298

280299
if (styling.underlineWidth > 0.dp && styling.underlineColor.isSpecified) {
281300
Spacer(Modifier.height(styling.underlineGap))
@@ -710,6 +729,28 @@ public open class DefaultMarkdownBlockRenderer(
710729
}
711730
}
712731

732+
@Composable
733+
private fun RenderImages(
734+
images: Map<String, InlineTextContent>,
735+
modifier: Modifier = Modifier,
736+
) {
737+
val density = LocalDensity.current
738+
FlowRow(modifier) {
739+
images.map { (text, inlineBlock) ->
740+
Box(
741+
modifier = with(density) {
742+
Modifier.size(
743+
inlineBlock.placeholder.width.toDp(),
744+
inlineBlock.placeholder.height.toDp(),
745+
)
746+
},
747+
) {
748+
inlineBlock.children(text)
749+
}
750+
}
751+
}
752+
}
753+
713754
public override fun createCopy(
714755
rootStyling: MarkdownStyling?,
715756
rendererExtensions: List<MarkdownRendererExtension>?,
@@ -734,9 +775,11 @@ private fun getImages(input: WithInlineMarkdown): List<InlineMarkdown.Image> = b
734775
is InlineMarkdown.Image -> {
735776
if (item.source.isNotBlank()) add(item)
736777
}
778+
737779
is WithInlineMarkdown -> {
738780
collectImagesRecursively(item.inlineContent)
739781
}
782+
740783
else -> {
741784
// Ignored
742785
}

platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
package com.intellij.ide.plugins;
33

44
import com.intellij.ide.IdeBundle;
5-
import com.intellij.ide.plugins.newui.TabbedPaneHeaderComponent;
65
import com.intellij.openapi.actionSystem.DataKey;
76
import com.intellij.openapi.application.ApplicationManager;
87
import com.intellij.openapi.application.ApplicationNamesInfo;
98
import com.intellij.openapi.application.ex.ApplicationManagerEx;
9+
import com.intellij.openapi.diagnostic.Logger;
1010
import com.intellij.openapi.extensions.PluginId;
1111
import com.intellij.openapi.options.Configurable;
1212
import com.intellij.openapi.options.ConfigurationException;
@@ -54,6 +54,8 @@ public final class PluginManagerConfigurable
5454

5555
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd, yyyy");
5656

57+
private static final Logger LOG = Logger.getInstance(PluginManagerConfigurable.class);
58+
5759
private PluginManagerConfigurablePanel myPanel;
5860

5961
/**
@@ -96,7 +98,12 @@ public String getDisplayName() {
9698
public @Nullable JComponent createComponent() {
9799
PluginManagerConfigurablePanel panel = createPanelIfNeeded();
98100

99-
getPluginsViewCustomizer().processConfigurable(this);
101+
try {
102+
getPluginsViewCustomizer().processConfigurable(this);
103+
}
104+
catch (Exception e) {
105+
LOG.error("Error while processing configurable", e);
106+
}
100107

101108
return panel.getComponent();
102109
}

platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurablePanel.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -902,22 +902,26 @@ protected void handleQuery(@NotNull String query, @NotNull PluginsGroup result,
902902
Map<PluginUiModel, Double> pluginToScore = null;
903903

904904
if (parser.internal) {
905-
PluginsViewCustomizer.PluginsGroupDescriptor groupDescriptor =
906-
PluginsViewCustomizerKt.getPluginsViewCustomizer().getInternalPluginsGroupDescriptor();
907-
if (groupDescriptor != null) {
908-
if (parser.searchQuery == null) {
909-
result.addDescriptors(groupDescriptor.getPlugins());
910-
}
911-
else {
912-
for (IdeaPluginDescriptor pluginDescriptor : groupDescriptor.getPlugins()) {
913-
if (StringUtil.containsIgnoreCase(pluginDescriptor.getName(), parser.searchQuery)) {
914-
result.addDescriptor(pluginDescriptor);
905+
try {
906+
PluginsViewCustomizer.PluginsGroupDescriptor groupDescriptor =
907+
PluginsViewCustomizerKt.getPluginsViewCustomizer().getInternalPluginsGroupDescriptor();
908+
if (groupDescriptor != null) {
909+
if (parser.searchQuery == null) {
910+
result.addDescriptors(groupDescriptor.getPlugins());
911+
}
912+
else {
913+
for (IdeaPluginDescriptor pluginDescriptor : groupDescriptor.getPlugins()) {
914+
if (StringUtil.containsIgnoreCase(pluginDescriptor.getName(), parser.searchQuery)) {
915+
result.addDescriptor(pluginDescriptor);
916+
}
915917
}
916918
}
919+
result.removeDuplicates();
920+
result.sortByName();
921+
return;
917922
}
918-
result.removeDuplicates();
919-
result.sortByName();
920-
return;
923+
} catch (Exception e) {
924+
LOG.error("Error while loading internal plugins group", e);
921925
}
922926
}
923927

platform/platform-impl/src/com/intellij/ide/plugins/newui/ListPluginComponent.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.intellij.openapi.actionSystem.*;
1212
import com.intellij.openapi.application.ApplicationManager;
1313
import com.intellij.openapi.application.ModalityState;
14+
import com.intellij.openapi.diagnostic.Logger;
1415
import com.intellij.openapi.extensions.PluginId;
1516
import com.intellij.openapi.progress.util.AbstractProgressIndicatorExBase;
1617
import com.intellij.openapi.project.DumbAwareAction;
@@ -59,6 +60,7 @@ public final class ListPluginComponent extends JPanel {
5960
public static final Color GRAY_COLOR = JBColor.namedColor("Label.infoForeground", new JBColor(Gray._120, Gray._135));
6061
public static final Color SELECTION_COLOR = JBColor.namedColor("Plugins.lightSelectionBackground", new JBColor(0xEDF6FE, 0x464A4D));
6162
public static final Color HOVER_COLOR = JBColor.namedColor("Plugins.hoverBackground", new JBColor(0xEDF6FE, 0x464A4D));
63+
private static final Logger LOG = Logger.getInstance(ListPluginComponent.class);
6264

6365
private static final Ref<Boolean> HANDLE_FOCUS_ON_SELECTION = new Ref<>(Boolean.TRUE);
6466

@@ -163,7 +165,12 @@ public ListPluginComponent(@NotNull PluginModelFacade pluginModelFacade,
163165

164166
UiInspectorUtil.registerProvider(this, new PluginIdUiInspectorContextProvider());
165167

166-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processListPluginComponent(this);
168+
try {
169+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processListPluginComponent(this);
170+
}
171+
catch (Exception e) {
172+
LOG.error("Error while customizing list plugin component", e);
173+
}
167174
}
168175

169176
@NotNull PluginsGroup getGroup() { return myGroup; }
@@ -335,7 +342,12 @@ public boolean isFocusable() {
335342
myAlignButton.setOpaque(false);
336343
}
337344

338-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processCreateButtons(this);
345+
try {
346+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processCreateButtons(this);
347+
}
348+
catch (Exception e) {
349+
LOG.error("Error while customizing create buttons", e);
350+
}
339351
}
340352

341353
private @NotNull InstallButton createInstallButton() {
@@ -856,7 +868,12 @@ private void removeButtons(boolean showRestart) {
856868
myAlignButton.setVisible(true);
857869
}
858870

859-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processRemoveButtons(this);
871+
try {
872+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processRemoveButtons(this);
873+
}
874+
catch (Exception e) {
875+
LOG.error("Error while customizing remove buttons", e);
876+
}
860877
}
861878

862879
public void updateButtons(PluginUiModel installedPlugin, PluginInstallationState state) {
@@ -893,7 +910,12 @@ private void doUpdateEnabledState() {
893910
updateErrors();
894911
setSelection(mySelection, false);
895912

896-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processUpdateEnabledState(this);
913+
try {
914+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processUpdateEnabledState(this);
915+
}
916+
catch (Exception e) {
917+
LOG.error("Error while customizing enabled state", e);
918+
}
897919
}
898920

899921
private void updateEnabledStateUI() {

platform/platform-impl/src/com/intellij/ide/plugins/newui/MultiSelectionEventHandler.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.intellij.openapi.actionSystem.*;
55
import com.intellij.openapi.application.ApplicationManager;
66
import com.intellij.openapi.application.ModalityState;
7+
import com.intellij.openapi.diagnostic.Logger;
78
import com.intellij.ui.ComponentUtil;
89
import org.jetbrains.annotations.ApiStatus;
910
import org.jetbrains.annotations.NotNull;
@@ -19,6 +20,7 @@
1920

2021
@ApiStatus.Internal
2122
public final class MultiSelectionEventHandler extends EventHandler {
23+
private static final Logger LOG = Logger.getInstance(MultiSelectionEventHandler.class);
2224
private PluginsGroupComponent myContainer;
2325
private PagePluginLayout myLayout;
2426
private List<ListPluginComponent> myComponents;
@@ -95,7 +97,12 @@ else if (mySelectionLength == 0 || mySelectionLength == 1) {
9597
return;
9698
}
9799

98-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processCreatePopupMenu(component, group, getSelection());
100+
try {
101+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processCreatePopupMenu(component, group, getSelection());
102+
}
103+
catch (Exception e) {
104+
LOG.error("Error while customizing popup menu", e);
105+
}
99106

100107
ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu("PluginManagerConfigurable", group);
101108
popupMenu.setTargetComponent(component);
@@ -188,7 +195,12 @@ else if (code == KeyEvent.VK_SPACE || code == KeyEvent.VK_ENTER || code == DELET
188195
}
189196
component.handleKeyAction(event, getSelection());
190197

191-
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processHandleKeyAction(component, event, getSelection());
198+
try {
199+
PluginsViewCustomizerKt.getListPluginComponentCustomizer().processHandleKeyAction(component, event, getSelection());
200+
}
201+
catch (Exception e) {
202+
LOG.error("Error while customizing handle key action", e);
203+
}
192204
}
193205
}
194206

0 commit comments

Comments
 (0)