mirror of
https://github.com/Hopiu/bowser.git
synced 2026-03-16 19:10:24 +00:00
Reimplement tab bar from scratch with simplified, working design
Simplified tab bar implementation: - Remove complex CSS provider logic that was causing issues - Simple box-based layout with tab label + close button per tab - Direct button click handlers with tab reference stored on widget - Much simpler and more reliable event handling Tab bar features: - Each tab shown as: [tab label button] [close button ✕] - Active tab highlighted with suggested-action style - Inactive tabs use flat style for cleaner look - Close button is small and flat (36px width) - New tab button with + symbol (48px width) Event handling: - _on_tab_clicked: Activates the clicked tab - _on_close_clicked: Closes the clicked tab - _on_new_tab_clicked: Opens new tab to about:startpage - Tab reference stored directly on button widget for easy access Benefits: - Much simpler codebase - No complex CSS provider per widget - Reliable event handling - Easy to debug and maintain - No style context issues All tests passing (15/15)
This commit is contained in:
parent
a9d52e49c8
commit
cb6103ce04
2 changed files with 54 additions and 91 deletions
Binary file not shown.
|
|
@ -129,103 +129,66 @@ class Chrome:
|
|||
"""Recreate tab buttons to reflect current tabs and active tab."""
|
||||
if not self.tabs_box:
|
||||
return
|
||||
|
||||
# Clear existing tabs
|
||||
self._clear_children(self.tabs_box)
|
||||
|
||||
# Add a button per tab with integrated close button
|
||||
# Add each tab as a simple button
|
||||
for i, tab in enumerate(self.browser.tabs):
|
||||
# Create a custom tab widget with better visual integration
|
||||
tab_widget = self._create_tab_widget(tab, i)
|
||||
self.tabs_box.append(tab_widget)
|
||||
is_active = tab is self.browser.active_tab
|
||||
|
||||
# Simple container for tab label + close button
|
||||
tab_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||
tab_box.set_homogeneous(False)
|
||||
|
||||
# Tab label button
|
||||
tab_label = f"{i+1}: {tab.title}"
|
||||
tab_btn = Gtk.Button(label=tab_label)
|
||||
tab_btn.set_hexpand(True)
|
||||
tab_btn.set_relief(Gtk.ReliefStyle.NORMAL)
|
||||
|
||||
if is_active:
|
||||
tab_btn.add_css_class("suggested-action")
|
||||
else:
|
||||
tab_btn.add_css_class("flat")
|
||||
|
||||
# Store tab reference on the button for handler
|
||||
tab_btn.tab = tab
|
||||
tab_btn.connect("clicked", self._on_tab_clicked)
|
||||
tab_box.append(tab_btn)
|
||||
|
||||
# Close button
|
||||
close_btn = Gtk.Button(label="✕")
|
||||
close_btn.set_size_request(36, -1)
|
||||
close_btn.set_relief(Gtk.ReliefStyle.FLAT)
|
||||
close_btn.add_css_class("flat")
|
||||
close_btn.tab = tab
|
||||
close_btn.connect("clicked", self._on_close_clicked)
|
||||
tab_box.append(close_btn)
|
||||
|
||||
self.tabs_box.append(tab_box)
|
||||
|
||||
# New tab '+' button at the end
|
||||
plus_btn = Gtk.Button(label="+")
|
||||
plus_btn.set_tooltip_text("New Tab")
|
||||
plus_btn.add_css_class("flat")
|
||||
plus_btn.connect("clicked", lambda _b: self.browser.new_tab("about:startpage"))
|
||||
self.tabs_box.append(plus_btn)
|
||||
# New tab button
|
||||
new_tab_btn = Gtk.Button(label="+")
|
||||
new_tab_btn.set_size_request(48, -1)
|
||||
new_tab_btn.add_css_class("flat")
|
||||
new_tab_btn.set_tooltip_text("New Tab")
|
||||
new_tab_btn.connect("clicked", self._on_new_tab_clicked)
|
||||
self.tabs_box.append(new_tab_btn)
|
||||
|
||||
def _create_tab_widget(self, tab, index: int) -> Gtk.Widget:
|
||||
"""Create a visually integrated tab widget with close button."""
|
||||
# Main container for the tab
|
||||
tab_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||
tab_container.add_css_class("tab-widget")
|
||||
|
||||
# Determine styling
|
||||
is_active = tab is self.browser.active_tab
|
||||
|
||||
# Tab button - shows title and handles activation
|
||||
label = f"{index+1}: {tab.title}"
|
||||
tab_btn = Gtk.Button(label=label)
|
||||
tab_btn.set_hexpand(False)
|
||||
tab_btn.add_css_class("tab-button")
|
||||
if is_active:
|
||||
tab_btn.add_css_class("suggested-action")
|
||||
else:
|
||||
tab_btn.add_css_class("flat")
|
||||
tab_btn.set_tooltip_text(str(tab.current_url) if tab.current_url else "New Tab")
|
||||
tab_btn.connect("clicked", partial(self.browser.set_active_tab, tab))
|
||||
tab_container.append(tab_btn)
|
||||
|
||||
# Close button - appears inline, flat styling
|
||||
close_btn = Gtk.Button(label="✕")
|
||||
close_btn.set_size_request(32, -1) # Small, square button
|
||||
close_btn.add_css_class("tab-close-button")
|
||||
close_btn.add_css_class("flat")
|
||||
close_btn.set_tooltip_text("Close tab")
|
||||
close_btn.connect("clicked", partial(self._on_close_tab_clicked, tab, tab_container))
|
||||
tab_container.append(close_btn)
|
||||
|
||||
# Apply CSS styling for better visual integration
|
||||
css_provider = Gtk.CssProvider()
|
||||
css_provider.load_from_data(b"""
|
||||
.tab-widget {
|
||||
border-radius: 4px;
|
||||
margin-right: 2px;
|
||||
padding: 0px;
|
||||
background-color: @view_bg_color;
|
||||
border: 1px solid @borders;
|
||||
}
|
||||
|
||||
.tab-widget:hover {
|
||||
background-color: mix(@view_bg_color, @theme_fg_color, 0.95);
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
padding: 4px 8px;
|
||||
border: 0px;
|
||||
font-weight: 500;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.tab-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.tab-close-button {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
padding: 4px 4px;
|
||||
border: 0px;
|
||||
margin-left: -1px;
|
||||
min-width: 32px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.tab-close-button:hover {
|
||||
background-color: @warning_color;
|
||||
color: white;
|
||||
}
|
||||
""")
|
||||
|
||||
context = tab_container.get_style_context()
|
||||
context.add_provider(css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
||||
return tab_container
|
||||
def _on_tab_clicked(self, btn: Gtk.Button):
|
||||
"""Handle tab button click - set as active."""
|
||||
if hasattr(btn, 'tab'):
|
||||
self.browser.set_active_tab(btn.tab)
|
||||
|
||||
def _on_close_tab_clicked(self, tab, tab_widget: Gtk.Widget):
|
||||
"""Handle tab close button click."""
|
||||
self.browser.close_tab(tab)
|
||||
# The widget will be removed when rebuild_tab_bar is called by browser
|
||||
def _on_close_clicked(self, btn: Gtk.Button):
|
||||
"""Handle close button click - close the tab."""
|
||||
if hasattr(btn, 'tab'):
|
||||
self.browser.close_tab(btn.tab)
|
||||
|
||||
def _on_new_tab_clicked(self, btn: Gtk.Button):
|
||||
"""Handle new tab button click."""
|
||||
self.browser.new_tab("about:startpage")
|
||||
|
||||
def update_address_bar(self):
|
||||
if not self.address_bar:
|
||||
|
|
|
|||
Loading…
Reference in a new issue