diff --git a/src/gui_2.py b/src/gui_2.py index f8339c6..a92a532 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -2309,14 +2309,16 @@ def hello(): return if not self.is_viewing_prior_session and imgui.collapsing_header("Discussions", imgui.TreeNodeFlags_.default_open): names = self._get_discussion_names() - if imgui.begin_combo("##disc_sel", self.active_discussion): + if imgui.begin_tab_bar("discussion_takes_tabs"): for name in names: - is_selected = (name == self.active_discussion) - if imgui.selectable(name, is_selected)[0]: - self._switch_discussion(name) - if is_selected: - imgui.set_item_default_focus() - imgui.end_combo() + # Only force selection if active_discussion changed externally + flags = imgui.TabItemFlags_.set_selected if name == self.active_discussion else 0 + opened, _ = imgui.begin_tab_item(name, None, flags) + if opened: + if name != self.active_discussion: + self._switch_discussion(name) + imgui.end_tab_item() + imgui.end_tab_bar() if self.active_track: imgui.same_line() changed, self._track_discussion_active = imgui.checkbox("Track Discussion", self._track_discussion_active) diff --git a/tests/test_gui_discussion_tabs.py b/tests/test_gui_discussion_tabs.py new file mode 100644 index 0000000..406c8dd --- /dev/null +++ b/tests/test_gui_discussion_tabs.py @@ -0,0 +1,48 @@ +import pytest +from unittest.mock import patch, MagicMock, PropertyMock + +from src import gui_2 + +@pytest.fixture +def mock_gui(): + gui = gui_2.App() + gui.project = { + 'discussion': { + 'active': 'main', + 'discussions': { + 'main': {'history': []}, + 'take_1': {'history': []}, + 'take_2': {'history': []} + } + } + } + gui.active_discussion = 'main' + # Mock some required state + gui.perf_profiling_enabled = False + gui.is_viewing_prior_session = False + gui._get_discussion_names = lambda: ['main', 'take_1', 'take_2'] + return gui + +def test_discussion_tabs_rendered(mock_gui): + with patch('src.gui_2.imgui') as mock_imgui, \ + patch('src.app_controller.AppController.active_project_root', new_callable=PropertyMock, return_value='.'): + # We expect a tab bar to be used instead of a combo box + mock_imgui.begin_tab_bar.return_value = True + mock_imgui.begin_tab_item.return_value = (True, True) + mock_imgui.input_text.return_value = (False, "") + mock_imgui.checkbox.return_value = (False, False) + mock_imgui.input_int.return_value = (False, 0) + + # Prevent infinite loop in ListClipper + mock_clipper = MagicMock() + mock_clipper.step.return_value = False + mock_imgui.ListClipper.return_value = mock_clipper + + mock_gui._render_discussion_panel() + + mock_imgui.begin_tab_bar.assert_called_once_with('discussion_takes_tabs') + # Check that begin_tab_item was called for each take + calls = [c[0][0] for c in mock_imgui.begin_tab_item.call_args_list] + assert 'main' in calls + assert 'take_1' in calls + assert 'take_2' in calls