Feature: Support chatting with multiple files (#306)

* Initial implementation

* Refactor UI related classes and organize imports

* Display selected files notification, include the files in the prompt

* feat: store referenced file paths in the messate state

* feat: add selected files accordion

* feat: update UI

* feat: improve file selection

* feat: support prompt template configuration

* fix: token calculation for virtualfile checkbox tree

* refactor: clean up

* refactor: move labels/descriptions to bundle
This commit is contained in:
Carl-Robert 2023-12-12 22:30:39 +02:00 committed by GitHub
parent 4354000ddb
commit f4be25bdac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 1125 additions and 148 deletions

View file

@ -0,0 +1,108 @@
package ee.carlrobert.codegpt.ui;
import static javax.swing.event.HyperlinkEvent.EventType.ACTIVATED;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBTextArea;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.toolwindow.chat.ui.SmartScroller;
import java.awt.Dimension;
import java.net.URISyntaxException;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class UIUtil {
public static JTextPane createTextPane(String text) {
return createTextPane(text, true);
}
public static JTextPane createTextPane(String text, boolean opaque) {
return createTextPane(text, opaque, UIUtil::handleHyperlinkClicked);
}
public static JTextPane createTextPane(String text, boolean opaque, HyperlinkListener listener) {
var textPane = new JTextPane();
textPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true);
textPane.addHyperlinkListener(listener);
textPane.setContentType("text/html");
textPane.setEditable(false);
textPane.setText(text);
textPane.setOpaque(opaque);
return textPane;
}
public static JBTextArea createTextArea(String initialValue) {
var textArea = new JBTextArea(initialValue);
textArea.setRows(3);
textArea.setBorder(JBUI.Borders.compound(
JBUI.Borders.customLine(JBColor.border()),
JBUI.Borders.empty(4)));
textArea.setLineWrap(true);
return textArea;
}
public static JButton createIconButton(Icon icon) {
var button = new JButton(icon);
button.setBorder(BorderFactory.createEmptyBorder());
button.setContentAreaFilled(false);
button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
return button;
}
public static JScrollPane createScrollPaneWithSmartScroller(ScrollablePanel scrollablePanel) {
var scrollPane = ScrollPaneFactory.createScrollPane(scrollablePanel, true);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
new SmartScroller(scrollPane);
return scrollPane;
}
public static void setEqualLabelWidths(JPanel firstPanel, JPanel secondPanel) {
var firstLabel = firstPanel.getComponents()[0];
var secondLabel = secondPanel.getComponents()[0];
if (firstLabel instanceof JLabel && secondLabel instanceof JLabel) {
firstLabel.setPreferredSize(secondLabel.getPreferredSize());
}
}
public static JPanel createPanel(JComponent component, String label, boolean resizeX) {
return UI.PanelFactory.panel(component)
.withLabel(label)
.resizeX(resizeX)
.createPanel();
}
public static void handleHyperlinkClicked(HyperlinkEvent event) {
var url = event.getURL();
if (ACTIVATED.equals(event.getEventType()) && url != null) {
try {
BrowserUtil.browse(url.toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}
public static void addShiftEnterInputMap(JTextArea textArea, AbstractAction onSubmit) {
textArea.getInputMap().put(KeyStroke.getKeyStroke("shift ENTER"), "insert-break");
textArea.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "text-submit");
textArea.getActionMap().put("text-submit", onSubmit);
}
}