Add chat font size controls

This commit is contained in:
kei 2026-05-30 22:31:31 +02:00
parent 1c7a8569fe
commit 30f0f93745
7 changed files with 151 additions and 0 deletions

View file

@ -7,6 +7,7 @@ public class GeneralSettingsState {
private String displayName = "";
private String avatarBase64 = "";
private ServiceType selectedService = null;
private int chatFontSizeOffset = 0;
public String getDisplayName() {
if (displayName == null || displayName.isEmpty()) {
@ -38,4 +39,12 @@ public class GeneralSettingsState {
public void setSelectedService(ServiceType selectedService) {
this.selectedService = selectedService;
}
public int getChatFontSizeOffset() {
return chatFontSizeOffset;
}
public void setChatFontSizeOffset(int chatFontSizeOffset) {
this.chatFontSizeOffset = chatFontSizeOffset;
}
}

View file

@ -0,0 +1,40 @@
package ee.carlrobert.codegpt.toolwindow.chat;
import com.intellij.util.ui.JBUI;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import javax.swing.JTextPane;
public final class ChatFontSize {
private static final int MIN_OFFSET = -4;
private static final int MAX_OFFSET = 8;
private ChatFontSize() {
}
public static boolean canAdjust(int delta) {
int offset = getOffset();
return delta < 0 ? offset > MIN_OFFSET : offset < MAX_OFFSET;
}
public static void adjust(int delta) {
var state = GeneralSettings.getCurrentState();
state.setChatFontSizeOffset(clampOffset(state.getChatFontSizeOffset() + delta));
}
public static void apply(JTextPane textPane) {
textPane.setFont(JBUI.Fonts.label().deriveFont((float) getFontSize()));
}
private static int getFontSize() {
return Math.max(8, JBUI.Fonts.label().getSize() + getOffset());
}
private static int getOffset() {
return clampOffset(GeneralSettings.getCurrentState().getChatFontSizeOffset());
}
private static int clampOffset(int offset) {
return Math.max(MIN_OFFSET, Math.min(MAX_OFFSET, offset));
}
}

View file

@ -1,8 +1,10 @@
package ee.carlrobert.codegpt.toolwindow.chat;
import com.intellij.icons.AllIcons;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultCompactActionGroup;
@ -39,6 +41,7 @@ import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.AttachImageNotifier;
import java.awt.CardLayout;
import java.nio.file.Path;
import java.util.Set;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.jetbrains.annotations.NotNull;
@ -199,6 +202,19 @@ public class ChatToolWindowPanel extends SimpleToolWindowPanel {
actionGroup.addSeparator();
actionGroup.add(new OpenInEditorAction());
actionGroup.addSeparator();
actionGroup.add(new AdjustChatFontSizeAction(
"Decrease chat font size",
"Decrease the chat message font size",
AllIcons.General.Remove,
-1,
tabbedPane));
actionGroup.add(new AdjustChatFontSizeAction(
"Increase chat font size",
"Increase the chat message font size",
AllIcons.General.Add,
1,
tabbedPane));
actionGroup.addSeparator();
actionGroup.add(new SelectedPersonaActionLink(project));
var toolbar = ActionManager.getInstance()
@ -207,6 +223,39 @@ public class ChatToolWindowPanel extends SimpleToolWindowPanel {
return toolbar;
}
private static class AdjustChatFontSizeAction extends DumbAwareAction {
private final int delta;
private final ChatToolWindowTabbedPane tabbedPane;
AdjustChatFontSizeAction(
String text,
String description,
Icon icon,
int delta,
ChatToolWindowTabbedPane tabbedPane) {
super(text, description, icon);
this.delta = delta;
this.tabbedPane = tabbedPane;
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.EDT;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
ChatFontSize.adjust(delta);
tabbedPane.refreshChatFontSize();
}
@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(ChatFontSize.canAdjust(delta));
}
}
private static class SelectedPersonaActionLink extends DumbAwareAction implements
CustomComponentAction {

View file

@ -202,6 +202,12 @@ public class ChatToolWindowTabPanel implements Disposable {
userInputPanel.requestFocus();
}
public void refreshChatFontSize() {
toolWindowScrollablePanel.refreshChatFontSize();
rootPanel.revalidate();
rootPanel.repaint();
}
public void displayLandingView() {
toolWindowScrollablePanel.displayLandingView(getLandingView());
totalTokensPanel.updateConversationTokens(conversation);

View file

@ -64,6 +64,12 @@ public class ChatToolWindowTabbedPane extends JBTabbedPane {
return activeTabMapping;
}
public void refreshChatFontSize() {
activeTabMapping.values().forEach(ChatToolWindowTabPanel::refreshChatFontSize);
repaint();
revalidate();
}
public void setTabLifecycleCallbacks(Runnable onTabsOpened, Runnable onAllTabsClosed) {
this.onTabsOpened = onTabsOpened;
this.onAllTabsClosed = onAllTabsClosed;

View file

@ -38,6 +38,7 @@ import ee.carlrobert.codegpt.settings.service.FeatureType;
import ee.carlrobert.codegpt.settings.models.ModelSettings;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
import ee.carlrobert.codegpt.toolwindow.chat.ChatFontSize;
import ee.carlrobert.codegpt.toolwindow.chat.editor.ResponseEditorPanel;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.header.DefaultHeaderPanel;
@ -59,6 +60,8 @@ import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.codegpt.ui.hover.PsiLinkHoverPreview;
import ee.carlrobert.codegpt.util.EditorUtil;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.util.Locale;
import java.util.Objects;
import javax.swing.DefaultListModel;
@ -276,6 +279,23 @@ public class ChatMessageResponseBody extends JPanel {
revalidate();
}
public void refreshFontSize() {
refreshFontSize(contentPanel);
revalidate();
repaint();
}
private static void refreshFontSize(Component component) {
if (component instanceof JTextPane textPane) {
ChatFontSize.apply(textPane);
}
if (component instanceof Container container) {
for (var child : container.getComponents()) {
refreshFontSize(child);
}
}
}
private void displayErrorMessage(String message, HyperlinkListener hyperlinkListener) {
ApplicationManager.getApplication().invokeLater(() -> {
if (webpageListPanel != null) {
@ -526,6 +546,7 @@ public class ChatMessageResponseBody extends JPanel {
UIUtil.handleHyperlinkClicked(event);
});
ChatFontSize.apply(textPane);
if (caretVisible) {
textPane.getCaret().setVisible(true);
textPane.setCaretPosition(textPane.getDocument().getLength());

View file

@ -3,6 +3,8 @@ package ee.carlrobert.codegpt.toolwindow.chat.ui;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
import ee.carlrobert.codegpt.toolwindow.ui.ResponseMessagePanel;
import java.awt.Component;
import java.awt.Container;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.HashMap;
@ -72,6 +74,24 @@ public class ChatToolWindowScrollablePanel extends ScrollablePanel {
revalidate();
}
public void refreshChatFontSize() {
for (var component : getComponents()) {
refreshChatFontSize(component);
}
update();
}
private static void refreshChatFontSize(Component component) {
if (component instanceof ChatMessageResponseBody responseBody) {
responseBody.refreshFontSize();
}
if (component instanceof Container container) {
for (var child : container.getComponents()) {
refreshChatFontSize(child);
}
}
}
public JPanel getLastComponent() {
var comp = getComponents()[getComponentCount() - 1];
if (comp instanceof JPanel panel) {