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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
- Added a global setting to choose the default dock position of the Claude Code session tab (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/24)

# 0.21.50 (2026-04-19)

- 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.3-SNAPSHOT</version>
<version>0.22.6-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
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@
*/
public final class ClaudeCodeOptionsPanel extends JPanel {

private static final String[] DOCK_MODE_VALUES = {
"editor", "commonpalette", "explorer", "navigator", "output"
};
private static final String[] DOCK_MODE_LABELS = {
"Editor area (default)", "Right side", "Left side top", "Left side bottom", "Bottom dock"
};

private static final String[] KEY_VALUES = {
ClaudeCodePreferences.ENTER,
ClaudeCodePreferences.SHIFT_ENTER,
Expand Down Expand Up @@ -68,6 +75,8 @@ public final class ClaudeCodeOptionsPanel extends JPanel {
private javax.swing.JCheckBox startNewSessionCheck;
/** Spinner for the maximum number of sessions shown in the session list. */
private JSpinner sessionListLimitSpinner;
/** Dropdown for the dock position of the Claude Code session tab. */
private javax.swing.JComboBox<String> dockModeCombo;
/** Spinner for the hang-detection timeout in seconds (0 = disabled). */
private JSpinner hangTimeoutSpinner;
/** Checkbox to enable MCP integration (pass --mcp-config flag). */
Expand Down Expand Up @@ -222,6 +231,13 @@ private JPanel buildGeneralPanel() {
form.add(sessionListLimitSpinner, gbc(1, row, false));
row++;

// --- session tab dock position ---
form.add(new JLabel("Session tab dock position:"), gbc(0, row, false));
dockModeCombo = new javax.swing.JComboBox<>(DOCK_MODE_LABELS);
dockModeCombo.setToolTipText("Where to dock the Claude Code session tab when opening it");
form.add(dockModeCombo, gbc(1, row, false));
row++;

// spacer
GridBagConstraints spacer = new GridBagConstraints();
spacer.gridx = 0; spacer.gridy = row;
Expand Down Expand Up @@ -357,6 +373,9 @@ void load() {
ClaudeCodePreferences.getContextMenuSessionMode()
== io.github.nbclaudecodegui.model.SessionMode.NEW);
sessionListLimitSpinner.setValue(ClaudeCodePreferences.getSessionListLimit());
String dockMode = ClaudeCodePreferences.getSessionDockMode();
int dockIdx = java.util.Arrays.asList(DOCK_MODE_VALUES).indexOf(dockMode);
dockModeCombo.setSelectedIndex(dockIdx >= 0 ? dockIdx : 0);
hangTimeoutSpinner.setValue(ClaudeCodePreferences.getHangTimeoutSeconds());
mcpEnabledCheckBox.setSelected(ClaudeCodePreferences.isMcpEnabled());

Expand Down Expand Up @@ -391,6 +410,11 @@ void store() {
? io.github.nbclaudecodegui.model.SessionMode.NEW
: io.github.nbclaudecodegui.model.SessionMode.CONTINUE_LAST);
ClaudeCodePreferences.setSessionListLimit((Integer) sessionListLimitSpinner.getValue());
int dockSel = dockModeCombo.getSelectedIndex();
ClaudeCodePreferences.setSessionDockMode(
dockSel >= 0 && dockSel < DOCK_MODE_VALUES.length
? DOCK_MODE_VALUES[dockSel]
: ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE);
ClaudeCodePreferences.setHangTimeoutSeconds((Integer) hangTimeoutSpinner.getValue());
ClaudeCodePreferences.setMcpEnabled(mcpEnabledCheckBox.isSelected());
ClaudeCodePreferences.setSendKey(selectedValue(sendRadios));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,25 @@ public static void setMcpEnabled(boolean v) {
NbPreferences.forModule(ClaudeCodePreferences.class).putBoolean(MCP_ENABLED, v);
}

// -------------------------------------------------------------------------
// sessionDockMode
// -------------------------------------------------------------------------

/** Preference key: dock mode for the Claude Code session tab. */
public static final String KEY_SESSION_DOCK_MODE = "sessionDockMode";
/** Default: editor area. */
public static final String DEFAULT_SESSION_DOCK_MODE = "editor";

public static String getSessionDockMode() {
return NbPreferences.forModule(ClaudeCodePreferences.class)
.get(KEY_SESSION_DOCK_MODE, DEFAULT_SESSION_DOCK_MODE);
}

public static void setSessionDockMode(String mode) {
NbPreferences.forModule(ClaudeCodePreferences.class)
.put(KEY_SESSION_DOCK_MODE, mode != null ? mode : DEFAULT_SESSION_DOCK_MODE);
}

private static String validated(String value, String fallback) {
return ENTER.equals(value) || SHIFT_ENTER.equals(value)
|| CTRL_ENTER.equals(value) || ALT_ENTER.equals(value)
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,17 @@ public ClaudeSessionTab(File dir) {
*
* <p>Focuses an existing idle session if one is open; otherwise opens a new one.
*/
private static void dockAndOpen(ClaudeSessionTab tab) {
String modeName = ClaudeCodePreferences.getSessionDockMode();
if (!ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE.equals(modeName)) {
org.openide.windows.Mode mode = WindowManager.getDefault().findMode(modeName);
if (mode != null) {
mode.dockInto(tab);
}
}
tab.open();
}

public static void openNewOrFocus() {
SwingUtilities.invokeLater(() -> {
for (TopComponent tc : WindowManager.getDefault().getRegistry().getOpened()) {
Expand All @@ -310,7 +321,7 @@ public static void openNewOrFocus() {
}
LOG.fine("openNewOrFocus: no idle tab found, opening new tab");
ClaudeSessionTab tab = new ClaudeSessionTab();
tab.open();
dockAndOpen(tab);
tab.requestActive();
});
}
Expand Down Expand Up @@ -342,7 +353,7 @@ public static void openForDirectory(File dir, String profileName) {
}
}
ClaudeSessionTab tab = new ClaudeSessionTab(dir);
tab.open();
dockAndOpen(tab);
tab.requestActive();
tab.autoStart(dir, profileName);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void tearDown() {
ClaudeCodePreferences.setMcpPort(ClaudeCodePreferences.DEFAULT_MCP_PORT);
ClaudeCodePreferences.setOpenDiffInSeparateTab(ClaudeCodePreferences.DEFAULT_OPEN_DIFF_IN_SEPARATE_TAB);
ClaudeCodePreferences.setMdPreviewInDiff(ClaudeCodePreferences.DEFAULT_MD_PREVIEW_IN_DIFF);
ClaudeCodePreferences.setSessionDockMode(ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE);
}

@Test
Expand Down Expand Up @@ -97,4 +98,24 @@ void mdPreviewInDiffStoreAndRetrieve() {
ClaudeCodePreferences.setMdPreviewInDiff(false);
assertFalse(ClaudeCodePreferences.isMdPreviewInDiff());
}

@Test
void sessionDockModeDefaultIsEditor() {
assertEquals(ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE,
ClaudeCodePreferences.getSessionDockMode());
assertEquals("editor", ClaudeCodePreferences.getSessionDockMode());
}

@Test
void sessionDockModeStoreAndRetrieve() {
ClaudeCodePreferences.setSessionDockMode("output");
assertEquals("output", ClaudeCodePreferences.getSessionDockMode());
}

@Test
void sessionDockModeNullFallsBackToDefault() {
ClaudeCodePreferences.setSessionDockMode(null);
assertEquals(ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE,
ClaudeCodePreferences.getSessionDockMode());
}
}
Loading