Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Fixed diff panel appearing at wrong height (nearly invisible) after Reset Windows or on first use
- Fixed second diff in the same Claude session being invisible (stale card accumulation)
- Fixed terminal scrolling to the beginning when a choice menu or diff panel appears (regression since 0.20.20)

# 0.21.46 (2026-04-17)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.nbclaudecodegui</groupId>
<artifactId>netbeans-claude-code-gui</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.22.3-SNAPSHOT</version>
<packaging>nbm</packaging>
<name>Netbeans Claude Code GUI</name>
<description>NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE.</description>
Expand Down
95 changes: 71 additions & 24 deletions src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,10 @@ public class ClaudeSessionTab extends TopComponent
private JediTermWidget terminalWidget;
private JSplitPane splitPane;
private JPanel errorPanel;
private JPanel southCard;
private CardLayout southCardLayout;
private String activeCard;
JPanel southCard;
CardLayout southCardLayout;
String activeCard;
JPanel currentDiffCard;
private Runnable pendingDiffOnClose;

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -741,19 +742,10 @@ private void showChatLayout(JediTermWidget widget) {
public void componentResized(ComponentEvent e) {
int total = splitPane.getHeight();
if (total <= 0) return;
int bottom;
if (!savingEnabled[0]) {
bottom = savedBottomHeight > 0 ? savedBottomHeight
: southCard.getPreferredSize().height;
savingEnabled[0] = true;
} else {
bottom = NbPreferences.forModule(ClaudeSessionTab.class)
.getInt(getSavedCardKey(), southCard.getPreferredSize().height);
}
int divLoc = total - splitPane.getDividerSize() - bottom;
LOG.fine(sessionTag + "[splitPane resize] total=" + total
+ " bottom=" + bottom + " divLoc=" + divLoc);
splitPane.setDividerLocation(divLoc);
LOG.fine(sessionTag + "[componentResized] activeCard=" + activeCard
+ " total=" + total + " savedBottomHeight=" + savedBottomHeight);
applyDividerForCard(activeCard, total, savedBottomHeight);
savingEnabled[0] = true;
}
});
splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, e -> {
Expand Down Expand Up @@ -893,11 +885,53 @@ private void showStartError(String command, String error,
* @return preference key string
*/
private String getSavedCardKey() {
if (CARD_PROMPT.equals(activeCard) || activeCard == null) return "bottomHeight";
return activeCard + "Height";
return getSavedCardKeyFor(activeCard);
}

/**
* Reads the saved divider height for {@code card}, falls back to sensible defaults,
* sets the divider location, and returns the bottom height used.
* {@code legacyPromptHeight} is the pre-migration "bottomHeight" value (pass -1 to skip).
*/
private int applyDividerForCard(String card, int total, int legacyPromptHeight) {
int saved = NbPreferences.forModule(ClaudeSessionTab.class)
.getInt(getSavedCardKeyFor(card), -1);
int bottom = computeBottomHeight(card, total, saved, legacyPromptHeight,
southCard.getPreferredSize().height);
int divLoc = total - splitPane.getDividerSize() - bottom;
LOG.fine(sessionTag + "[applyDivider] card=" + card
+ " total=" + total + " saved=" + saved
+ " legacy=" + legacyPromptHeight
+ " preferred=" + southCard.getPreferredSize().height
+ " bottom=" + bottom + " divLoc=" + divLoc);
if (divLoc >= 0) splitPane.setDividerLocation(divLoc);
return bottom;
}

/**
* Pure function: computes the south-panel height for a given card.
* Extracted for unit testing — no Swing state access.
*
* @param card active card name (CARD_PROMPT or CARD_DIFF)
* @param total total splitPane height
* @param saved persisted height (negative means not saved)
* @param legacyPromptHeight "bottomHeight" pref value for backward-compat (negative to skip)
* @param preferredHeight southCard preferred height (fallback)
*/
static int computeBottomHeight(String card, int total, int saved,
int legacyPromptHeight, int preferredHeight) {
if (saved > 0) return saved;
if (CARD_DIFF.equals(card)) return total * 2 / 3;
if (CARD_PROMPT.equals(card) && legacyPromptHeight > 0) return legacyPromptHeight;
return preferredHeight;
}

private void switchSouthCard(String card) {
String getSavedCardKeyFor(String card) {
if (CARD_PROMPT.equals(card) || card == null) return "bottomHeight";
return card + "Height";
}

void switchSouthCard(String card) {
if (southCard == null || southCardLayout == null) return;
activeCard = card;
southCardLayout.show(southCard, card);
Expand All @@ -912,11 +946,14 @@ private void switchSouthCard(String card) {
if (!CARD_CHOICE.equals(card)) {
// restore divider for this card
int total = splitPane.getHeight();
LOG.fine(sessionTag + "[switchSouthCard] card=" + card + " total=" + total);
if (total > 0) {
int bottom = NbPreferences.forModule(ClaudeSessionTab.class)
.getInt(getSavedCardKey(), DEFAULT_DIFF_HEIGHT);
int divLoc = total - splitPane.getDividerSize() - bottom;
splitPane.setDividerLocation(divLoc);
applyDividerForCard(card, total, -1);
} else {
SwingUtilities.invokeLater(() -> {
int t = splitPane != null ? splitPane.getHeight() : 0;
if (t > 0) applyDividerForCard(activeCard, t, -1);
});
}
} else {
// lock divider for choice menu
Expand Down Expand Up @@ -1058,6 +1095,7 @@ private void cleanupChatLayout() {
southCard = null;
southCardLayout = null;
activeCard = null;
currentDiffCard = null;
}
if (errorPanel != null) {
remove(errorPanel);
Expand Down Expand Up @@ -1124,14 +1162,19 @@ public boolean showEmbeddedDiff(boolean outsideProject, String outsideWarning,
permPanel.showWarning(outsideWarning);
}

if (currentDiffCard != null) {
southCard.remove(currentDiffCard);
currentDiffCard = null;
}
JPanel diffCard = new JPanel(new BorderLayout());
if (toolbar != null) {
diffCard.add(toolbar, BorderLayout.NORTH);
}
diffCard.add(diffComponent, BorderLayout.CENTER);
diffCard.add(permPanel, BorderLayout.SOUTH);

southCard.add(diffCard, CARD_DIFF);
currentDiffCard = diffCard;
southCard.add(currentDiffCard, CARD_DIFF);

pendingDiffOnClose = onTabClose;
switchSouthCard(CARD_DIFF);
Expand All @@ -1148,6 +1191,10 @@ public void hideEmbeddedDiff() {
pendingDiffOnClose = null;
if (southCard == null) return;
switchSouthCard(CARD_PROMPT);
if (currentDiffCard != null) {
southCard.remove(currentDiffCard);
currentDiffCard = null;
}
revalidate();
repaint();
}
Expand Down
Loading