Compare commits

...

11 Commits

3 changed files with 160 additions and 150 deletions

View File

@ -3,7 +3,13 @@
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<requires lib="Adw" version="1.0"/> <requires lib="Adw" version="1.0"/>
<menu id="import_menu"> <menu id="sidebar_menu">
<section>
<item>
<attribute name="label">Add Project</attribute>
<attribute name="action">win.add-project</attribute>
</item>
</section>
<section> <section>
<item> <item>
<attribute name="label">Import from OpenAPI / Swagger</attribute> <attribute name="label">Import from OpenAPI / Swagger</attribute>
@ -18,27 +24,36 @@
<attribute name="action">win.import-http-file</attribute> <attribute name="action">win.import-http-file</attribute>
</item> </item>
</section> </section>
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">app.shortcuts</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Roster</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu> </menu>
<template class="RosterWindow" parent="AdwApplicationWindow"> <template class="RosterWindow" parent="AdwApplicationWindow">
<property name="default-width">1200</property> <property name="default-width">1200</property>
<property name="default-height">800</property> <property name="default-height">800</property>
<property name="width-request">470</property>
<property name="content"> <property name="content">
<object class="AdwToastOverlay" id="toast_overlay"> <object class="AdwToastOverlay" id="toast_overlay">
<property name="child"> <property name="child">
<object class="GtkPaned" id="main_pane"> <object class="AdwOverlaySplitView" id="split_view">
<property name="orientation">horizontal</property> <property name="min-sidebar-width">200</property>
<property name="position">180</property> <property name="max-sidebar-width">320</property>
<property name="shrink-start-child">False</property>
<property name="resize-start-child">True</property>
<property name="shrink-end-child">False</property>
<property name="resize-end-child">True</property>
<property name="wide-handle">False</property>
<!-- LEFT: Sidebar Panel with AdwToolbarView --> <!-- LEFT: Sidebar Panel with AdwToolbarView -->
<property name="start-child"> <property name="sidebar">
<object class="AdwToolbarView"> <object class="AdwToolbarView">
<property name="width-request">200</property>
<!-- Sidebar Header Bar --> <!-- Sidebar Header Bar -->
<child type="top"> <child type="top">
@ -59,20 +74,11 @@
</object> </object>
</child> </child>
<child type="end"> <child type="end">
<object class="GtkButton" id="add_project_button"> <object class="GtkMenuButton" id="sidebar_hamburger_button">
<property name="icon-name">list-add-symbolic</property> <property name="primary">True</property>
<property name="tooltip-text">Add Project</property> <property name="icon-name">open-menu-symbolic</property>
<signal name="clicked" handler="on_add_project_clicked"/> <property name="tooltip-text">Menu</property>
<style> <property name="menu-model">sidebar_menu</property>
<class name="flat"/>
</style>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="import_menu_button">
<property name="icon-name">papyrus-vertical-symbolic</property>
<property name="tooltip-text">Import</property>
<property name="menu-model">import_menu</property>
<style> <style>
<class name="flat"/> <class name="flat"/>
</style> </style>
@ -105,7 +111,7 @@
</property> </property>
<!-- RIGHT: Main Content Panel with AdwToolbarView --> <!-- RIGHT: Main Content Panel with AdwToolbarView -->
<property name="end-child"> <property name="content">
<object class="AdwToolbarView"> <object class="AdwToolbarView">
<!-- Main Header Bar --> <!-- Main Header Bar -->
@ -115,6 +121,20 @@
<property name="show-start-title-buttons">False</property> <property name="show-start-title-buttons">False</property>
<property name="show-end-title-buttons">False</property> <property name="show-end-title-buttons">False</property>
<!-- Sidebar toggle (only visible when collapsed) -->
<child type="start">
<object class="GtkToggleButton" id="sidebar_toggle_button">
<property name="icon-name">sidebar-show-symbolic</property>
<property name="tooltip-text">Show Sidebar</property>
<style>
<class name="flat"/>
</style>
<binding name="visible">
<lookup name="collapsed">split_view</lookup>
</binding>
</object>
</child>
<!-- Left side buttons --> <!-- Left side buttons -->
<child type="start"> <child type="start">
<object class="GtkButton" id="save_request_button"> <object class="GtkButton" id="save_request_button">
@ -126,7 +146,6 @@
</style> </style>
</object> </object>
</child> </child>
<child type="start"> <child type="start">
<object class="GtkButton" id="export_request_button"> <object class="GtkButton" id="export_request_button">
<property name="icon-name">export-symbolic</property> <property name="icon-name">export-symbolic</property>
@ -138,13 +157,15 @@
</object> </object>
</child> </child>
<!-- Window controls: separate end child so it's always rightmost -->
<child type="end">
<object class="GtkWindowControls">
<property name="side">end</property>
</object>
</child>
<!-- Right side buttons --> <!-- Right side buttons -->
<child type="end"> <child type="end">
<object class="GtkBox">
<property name="spacing">6</property>
<!-- New Request Button -->
<child>
<object class="GtkButton" id="new_request_button"> <object class="GtkButton" id="new_request_button">
<property name="icon-name">list-add-symbolic</property> <property name="icon-name">list-add-symbolic</property>
<property name="tooltip-text">New Request (Ctrl+T)</property> <property name="tooltip-text">New Request (Ctrl+T)</property>
@ -153,25 +174,6 @@
</style> </style>
</object> </object>
</child> </child>
<!-- Main Menu -->
<child>
<object class="GtkMenuButton">
<property name="primary">True</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="tooltip-text" translatable="yes">Main Menu</property>
<property name="menu-model">primary_menu</property>
</object>
</child>
<!-- Window Controls -->
<child>
<object class="GtkWindowControls">
<property name="side">end</property>
</object>
</child>
</object>
</child>
</object> </object>
</child> </child>
@ -256,22 +258,14 @@
</property> </property>
</object> </object>
</property> </property>
<!-- Collapse sidebar when window is narrow -->
<child>
<object class="AdwBreakpoint">
<condition>max-width: 700sp</condition>
<setter object="split_view" property="collapsed">True</setter>
</object>
</child>
</template> </template>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">app.shortcuts</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Roster</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
</interface> </interface>

View File

@ -115,6 +115,7 @@ class RequestTabWidget(Gtk.Box):
self.url_entry = Gtk.Entry() self.url_entry = Gtk.Entry()
self.url_entry.set_placeholder_text("Enter URL...") self.url_entry.set_placeholder_text("Enter URL...")
self.url_entry.set_hexpand(True) self.url_entry.set_hexpand(True)
self.url_entry.add_css_class("url-entry")
self.url_box.append(self.url_entry) self.url_box.append(self.url_entry)
# Send Button # Send Button
@ -131,10 +132,10 @@ class RequestTabWidget(Gtk.Box):
split_pane = Gtk.Paned(orientation=Gtk.Orientation.HORIZONTAL) split_pane = Gtk.Paned(orientation=Gtk.Orientation.HORIZONTAL)
split_pane.set_vexpand(True) split_pane.set_vexpand(True)
split_pane.set_position(UI_PANE_REQUEST_RESPONSE_POSITION) split_pane.set_position(UI_PANE_REQUEST_RESPONSE_POSITION)
split_pane.set_shrink_start_child(False) split_pane.set_shrink_start_child(True) # request can collapse to 0
split_pane.set_shrink_end_child(False) split_pane.set_shrink_end_child(False) # response stays
split_pane.set_resize_start_child(True) split_pane.set_resize_start_child(True) # request gives up space first
split_pane.set_resize_end_child(True) split_pane.set_resize_end_child(False) # response keeps its size
# Request Panel # Request Panel
request_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) request_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
@ -165,6 +166,7 @@ class RequestTabWidget(Gtk.Box):
# Response Panel # Response Panel
response_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) response_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
response_box.set_size_request(250, -1)
# Stack switcher (placed in bottom bar together with status info) # Stack switcher (placed in bottom bar together with status info)
response_switcher = Gtk.StackSwitcher() response_switcher = Gtk.StackSwitcher()

View File

@ -19,7 +19,7 @@
import gi import gi
gi.require_version('GtkSource', '5') gi.require_version('GtkSource', '5')
from gi.repository import Adw, Gtk, GLib, Gio, GtkSource from gi.repository import Adw, Gtk, GLib, Gio, GtkSource, GObject
from typing import Dict, Optional from typing import Dict, Optional
import logging import logging
from .models import HttpRequest, HttpResponse, HistoryEntry, RequestTab from .models import HttpRequest, HttpResponse, HistoryEntry, RequestTab
@ -63,14 +63,12 @@ class RosterWindow(Adw.ApplicationWindow):
tab_view = Gtk.Template.Child() tab_view = Gtk.Template.Child()
tab_bar = Gtk.Template.Child() tab_bar = Gtk.Template.Child()
# Panes # Split view
main_pane = Gtk.Template.Child() split_view = Gtk.Template.Child()
sidebar_toggle_button = Gtk.Template.Child()
# Sidebar widgets # Sidebar widgets
projects_listbox = Gtk.Template.Child() projects_listbox = Gtk.Template.Child()
add_project_button = Gtk.Template.Child()
import_menu_button = Gtk.Template.Child()
# History (hidden but kept for compatibility) # History (hidden but kept for compatibility)
history_listbox = Gtk.Template.Child() history_listbox = Gtk.Template.Child()
@ -102,6 +100,14 @@ class RosterWindow(Adw.ApplicationWindow):
# Setup custom CSS # Setup custom CSS
self._setup_custom_css() self._setup_custom_css()
# Bind sidebar toggle button to split view (bidirectional)
self.split_view.bind_property(
'show-sidebar',
self.sidebar_toggle_button,
'active',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE
)
# Setup UI # Setup UI
self._setup_tab_system() self._setup_tab_system()
self._load_projects() self._load_projects()
@ -204,6 +210,11 @@ class RosterWindow(Adw.ApplicationWindow):
font-weight: 600; font-weight: 600;
} }
/* URL entry can shrink to near-zero so the Send button stays visible */
entry.url-entry {
min-width: 0;
}
/* Method chips in sidebar request list */ /* Method chips in sidebar request list */
.method-chip { .method-chip {
border-radius: 4px; border-radius: 4px;
@ -508,6 +519,10 @@ class RosterWindow(Adw.ApplicationWindow):
self.add_action(action) self.add_action(action)
self.get_application().set_accels_for_action("win.send-request", ["<Control>Return"]) self.get_application().set_accels_for_action("win.send-request", ["<Control>Return"])
action = Gio.SimpleAction.new("add-project", None)
action.connect("activate", lambda a, p: self.on_add_project_clicked(None))
self.add_action(action)
action = Gio.SimpleAction.new("import-openapi", None) action = Gio.SimpleAction.new("import-openapi", None)
action.connect("activate", lambda a, p: self.on_import_openapi_clicked(None)) action.connect("activate", lambda a, p: self.on_import_openapi_clicked(None))
self.add_action(action) self.add_action(action)
@ -949,7 +964,6 @@ class RosterWindow(Adw.ApplicationWindow):
item.connect('manage-environments-requested', self._on_manage_environments, project) item.connect('manage-environments-requested', self._on_manage_environments, project)
self.projects_listbox.append(item) self.projects_listbox.append(item)
@Gtk.Template.Callback()
def on_add_project_clicked(self, button): def on_add_project_clicked(self, button):
"""Show dialog to create project.""" """Show dialog to create project."""
dialog = Adw.AlertDialog() dialog = Adw.AlertDialog()