Якщо ви тільки починаєте своє знайомство з фреймворком GTK, можливо, як і в мене, виникне схожа дилема з обмеженою функціональністю класичного віджету для створення вкладок GtkNotebook. В мережі віднайшов матеріал 2021 року "Reinventing tabs", в якому розглядається проблема стандартного віджету та пропонується альтернатива - HdyTab.
Переосмислення вкладок
В робочому столі GNOME 40, браузер Epiphany має нову панель вкладок. Це не просто переробка старої панелі, а повне її переписування з нуля:
Але для чого це було необхідно?
Статичні та динамічні вкладки
Додатки GNOME використовують вкладки різними способами, їх можна приблизно поділити на дві категорії.
Статичні вкладки
Вони є повністю незмінними, кожна вкладка містить заголовок і зазвичай не прокручуються. Зазвичай їх використовують у діалогових вікнах, але, наприклад, їх також можна використовувати в панелях інструментів. Сучасні додатки часто використовують GtkStackSwitcher
або HdyViewSwitcher
, але GtkNotebook
все ще досить поширений.
Динамічні вкладки
Цей тип вкладок використовується в багатовіконних додатках, таких як веб-браузери, текстові редактори, файлові менеджери або емулятори терміналів. Вони відкриваються та закриваються користувачем, їх можна змінювати за порядком, перетягувати між вікнами або в нові вікна, скидаючи їх на робочий стіл. Вони часто реалізують прокрутку. Завжди мають заголовок і кнопку закриття, іноді іконку та/або індикатор завантаження. Вони ховаються, коли присутня лише одна вкладка. Їх можна закривати середнім кліком або через контекстне меню. Іноді, динамічні вкладки можна закріпити або додати іконку, наприклад, індикатор відтворення аудіо чи діалог підтвердження закриття.
Чому така різниця?
Хоча статичні вкладки в GNOME досить однорідні, динамічні вкладки в різних додатках виглядають і відчуваються дуже по-різному.
Наприклад:
- в GNOME Text Editor - кнопки закриття є лише в обраних вкладках, або при наведені на вкладку, тоді як в інших додатках - вони присутні на всіх вкладках
- деякі додатки дозволяють вкладкам зменшуватися до малого розміру перед прокруткою, інші починають прокручуватися раніше
- Devhelp - взагалі не прокручує вкладки, а просто виводить їх за межі вікна
- Epiphany та GNOME Terminal - мають спливаючі вікна, що показують усі ці вкладки; GNOME Terminal використовує
GtkMenu
, тоді як Epiphany - використовуєGtkPopover
- хоча це не видно на скріншоті, лише Epiphany та gedit підтримують перетягування вкладок між вікнами
- в Epiphany та Nautilus - можна перетягувати файли на вкладки. У Nautilus, якщо ви наведете курсор на вкладку під час перетягування файлу, вона автоматично переключиться на цю вкладку, але не в Epiphany
- У gedit та GNOME Terminal - неможливо зосередити фокус на активній вкладці, натискаючи на неї знову
- У GNOME Text Editor та Epiphany - при переході на іншу вкладку, коли відбувся фокус на активну вкладку, її фокус буде здійснено на сторінку а не саму вкладку
GtkNotebook
Усі додатки вище використовують віджет під назвою GtkNotebook
. Він реалізує загальний вигляд з вкладками та показує вкладки з одного боку, причому кожна вкладка має заголовок, який можна замінити на будь-який інший віджет.
За замовчуванням, GtkNotebook
не має засобів прокручування, має простий заголовок на кожній вкладці, не розширює вкладки та не дозволяє жодного виду перетягування.
Іншими словами, він орієнтований виключно на статичні вкладки. Це не означає, що його неможливо використовувати для динамічних вкладок, але вам доведеться вручну реалізувати наступне:
- макет вкладок з кнопкою закриття, заголовком, іконкою та, можливо, індикатором беззвучного режиму, а також встановити розумну мінімальну ширину для прокрутки
- гарячі клавіші, такі як
Ctrl+Tab
абоAlt+[1-9]
для перемикання між вкладками - обробку контекстного меню, включаючи гарячі клавіші та жест довгого натискання для сенсорних екранів
- закриття середнім кліком
- логіку відкриття/закриття вкладок - наприклад, яку вкладку вибрати, коли активна вкладка закрита
- якщо потрібно скинути дані на вкладки, обробник для цього. Також потрібно бути обережним, щоб випадково не зламати тайм-аут наведення в процесі, як це робить Epiphany у версії 3.38.x
- авто-приховування контейнера, коли в ньому присутня лише одна вкладка
Ці вимоги підкреслюють, що хоча GtkNotebook
може бути використаний для динамічних вкладок, його базова реалізація не підтримує багато функцій, які користувачі очікують від сучасних динамічних вкладок, і вимагає значних зусиль для налаштування.
Звісно, кожен додаток реалізує ці функції трохи по-різному. А ще є проблеми, які не можна повністю вирішити з боку додатка, такі як:
- прокручування вкладок є дискретним, це виглядає заплутано і викликає інші проблеми:
- динамічні вкладки можуть мати велику кількість вкладок, натискання стрілок для прокрутки по одній вкладці за раз не є ефективним у цьому випадку
- пов'язано з цим, неможливо взяти вкладку і перемістити її на великі відстані; вам доведеться перемістити її на кілька вкладок вперед, натиснути кнопки прокрутки кілька разів, знову перемістити тощо
- при відкритті нової вкладки вона може опинитися за межами екрану без очікування такої поведінки
- мінімальна ширина вкладки змінюється в залежності від розміру вікна
- відсутня функціональність закріплених вкладок
- інтерфейс загалом не дуже відшліфований - наприклад, не має анімації при відкритті або закритті вкладок
Ці проблеми підкреслюють, що, хоча додатки можуть намагатись реалізувати динамічні вкладки засобами статичного віджета GtkNotebook
, існують обмеження, які ускладнюють створення зручного та інтуїтивно зрозумілого досвіду для користувачів.
Деякі з таких проблем можна замаскувати:
- Epiphany імітує закріплені вкладки, примусово переміщуючи їх на початок, використовуючи компактний макет, не розширюючи їх і не дозволяючи закривати. Однак ці вкладки все ще можуть бути прокручені, і те, що ширина вкладок змінюється в залежності від розміру вікна, особливо негативно впливає на зовнішній вигляд:
- Epiphany вручну підсвічує стрілки, коли вкладка була відкрита за межами екрана, також надає спливаюче вікно для швидкого перемикання між вкладками, коли вони не вміщаються на екрані, однак це не допомагає з перестановкою вкладок
- динамічний віджет DynamicNotebook в Elementary реалізує затримку зміни розміру після закриття вкладки, але це не завжди надійно; наприклад, він стрибає, коли стрілки прокрутки зникають, крім того, він може працювати лише тоді, коли вкладки не розширені
- ці особливості підкреслюють, що, хоча обидва додатки намагаються покращити управління вкладками, існують обмеження, які можуть призвести до непередбачуваного або незручного досвіду для користувачів; підсвічування стрілок може бути корисним, але не вирішує основну проблему з доступом до вкладок, які відкриваються за межами екрана; затримка зміни розміру може бути корисною, але її ненадійність може викликати додаткові труднощі
Крім того, GtkNotebook
містить як вміст, так і вкладки, і вони є невід'ємними, тому неможливо мати вкладки у повноекранному режимі, автоматично приховуючи їх з заголовної панелі, або розміщувати їх у панелі заголовку, відокремлено від вмісту.
Нарешті, GtkNotebook
не є адаптивним, і Epiphany наразі має вбудовану реалізацію мобільного перемикача вкладок, яку кожен додаток, що прагне адаптивного інтерфейсу з вкладками - повинен буде копіювати.
Ці обмеження підкреслюють, що GtkNotebook
не забезпечує гнучкості, необхідної для сучасних інтерфейсів, які можуть адаптуватися до різних розмірів екранів і режимів використання. Відсутність можливості розміщення вкладок окремо від вмісту обмежує можливості дизайну, а необхідність копіювати реалізацію мобільного перемикача вкладок може призвести до дублювання зусиль і несумісності між додатками.
HdyTab як рішення
Отже, з урахуванням усіх цих обмежень, я вважаю, що найчистішим шляхом вперед є створення абсолютно нового віджета, який реалізує специфічно динамічні вкладки. Таким чином, також зможемо відокремити перегляд вкладок і панель вкладок в окремі віджети, так само як GtkStack
і GtkStackSwitcher
- є окремими.
Реалізацію цього віджета було розпочато незадовго до GUADEC 2020 року, і до кінця вересня, на момент долучення до Purism - її було майже завершено. У січні ми з Адрієном нарешті знайшли час, щоб закінчити, переглянути та впровадити його.
Результатом цього стали два віджети під назвою HdyTabView
і HdyTabBar
, доступні в бібліотеці libhandy, починаючи з версії 1.2
HdyTabView
містить GtkStack
і надає API, більш придатний для динамічних вкладок: наприклад, сторінки відтепер строго впорядковані, є API для перестановки вкладок тощо. Крім того, кожна сторінка має велику кількість метаданих, вона використовує об'єкти сторінок, схожі на GTK 4 (HdyTabPage
), навіть у GTK 3, замість властивостей дочірніх елементів, які було б досить незручно використовувати без прив'язок властивостей.
HdyTabBar
є панеллю вкладок, яка підключається до HdyTabView
і відображає його сторінки, реалізуючи цей дизайн:
Що він забезпечує
- вкладки мають іконку, заголовок, підказку, кнопку закриття, контекстне меню, і вони можуть показувати індикатор завантаження замість іконки
- закріплені вкладки: вони компактні, розташовані на початку панелі вкладок і не прокручуються разом з іншими вкладками; вони також впливають на поведінку гарячих клавіш, таких як
Ctrl+Home/End
- індикатори непрочитаних повідомлень, включаючи випадки, коли непрочитана вкладка прокручується за межі екрану:
- піктограми-індикатори: кожна сторінка може мати одну піктограму-індикатор на вкладці, опціонально доступну для натискання; Epiphany використовує його як індикатор відтворення аудіо/кнопку вимкнення звуку, а індикатори - розташовані зліва від вкладки, щоб не конфліктувати з кнопками закриття:
Коли вкладка закріплена, індикатор відображається замість іконки, а не поруч з нею, як це було раніше в Epiphany. Щоб забезпечити легкий вибір вкладки, вона є клікабельною лише тоді, коли вкладка вже вибрана, тому перший клік вибирає вкладку, а другий клік - активує індикатор.
-
автоматичне приховування, коли присутня лише одна вкладка
-
при закритті вкладок за допомогою вказівника, вони не заповнюють порожній простір одразу, натомість вони змінюють розмір так, щоб кнопка закриття наступної вкладки перемістилася точно туди, де була остання, що дозволяє закривати кілька вкладок поспіль, не переміщуючи вказівник
-
автоматичне позиціонування для нових вкладок, хоча також є API для вставки вкладок у довільні позиції, якщо це потрібно
-
повноцінна підтримка перетягування: вкладки можна переставляти, переміщувати між вікнами, скидувати на робочий стіл для створення нового вікна, вкладки можуть приймати довільні дані, які скидаються; якщо панель вкладок має лише одну вкладку, вона автоматично відображається, коли починається перетягування, і приховується, коли воно закінчується, тому все ще можливо скинути іншу вкладку в неї
-
вкладки також можна скинути на перегляд вкладок; в цьому випадку вони додаються в кінець панелі вкладок
-
підтримка сенсорних екранів: перетягніть панель вкладок, щоб прокрутити її, довге натискання і перетягування для перестановки вкладки, довше натискання для відкриття контекстного меню
-
API підтвердження закриття
-
відкриття, закриття, перестановка вкладок, перетягування, показування та приховування панелі вкладок - анімовані
-
гарячі клавіші:
-
Ctrl+Tab
іShift+Ctrl+Tab
- перемикання між вкладками з обгортанням -
Ctrl+PageUp/PageDown/Home/End
- те ж саме, але без обгортання -
Ctrl+Shift+PageUp/PageDown/Home/End
- перестановка вкладок -
Alt+[1–9]
- перемикання на одну з перших 9 вкладок
-
Той факт, що вони є окремими, дозволяє Epiphany зберігати свою панель вкладок у повноекранному режимі в 40 версії:
Чого він не забезпечує
- фіксований макет вкладок:
HdyTabView
не дозволяє встановлювати довільний віджет як макет вкладок; макет є фіксованим і керується виключно через властивостіHdyTabPage
- відсутність окремого управління перестановкою та від'єднанням: не можна окремо включати або вимикати перестановку та від'єднання для різних вкладок; вкладки завжди можна переставляти та від'єднувати, і немає можливості це вимкнути
- відсутність контролю над розширенням вкладок: аналогічно, немає можливості зробити так, щоб певні вкладки розширювалися або не розширювалися, усі вкладки (за винятком закріплених) за замовчуванням - розширені
- кнопки закриття: у всіх вкладках (за винятком закріплених) є кнопки закриття, їх не можна видалити, хоча можливо затримати та/або відхилити запит на закриття, наприклад, якщо додаток хоче показати діалог підтвердження при закритті вкладки
- видимість кнопок закриття: кнопки закриття видимі лише на вибраних та/або наведені вкладки, немає можливості показувати їх на всіх вкладках
- вертикальні вкладки:
HdyTabBar
є строго горизонтальним, і його макет не має сенсу у вертикальному вигляді, однак він має API для спостереження за своїми сторінками черезGListModel
(GtkSelectionModel
у GTK 4), тому дуже легко створити вертикальний список замість цього
Оскільки Epiphany також використовується в Elementary OS, HdyTabBar
надає API для вимкнення автоматичного приховування та розширення вкладок, а також для зміни місцями кнопки закриття та індикатора. Усі ці параметри все ще працюють так, як і раніше.
Адаптивність
HdyTabBar
поки що не є адаптивним. Epiphany все ще постачає той самий мобільний інтерфейс у версії 40. Однак це значно полегшує реалізацію альтернативних комутаторів, наприклад, нижній аркуш на основі HdyFlap
:
Однак це дуже базово. Мобільні перемикачі вкладок часто є дуже складними, наприклад, використовують 3D-стеки карток, сітки, каруселі або списки з попередніми переглядами. На жаль, усе це недоступно в GTK 3. Однак у GTK 4 це можливо, і ми можемо робити такі речі:
Маючи належний огляд, можна буде нарешті видалити спливаюче вікно вкладок з Epiphany, яке все ще є в 40 версії, але показується лише тоді, коли панель вкладок починає прокручуватися.
Порт HdyTabView
і HdyTabBar
на GTK 4 завершено і повністю працює, і йому просто потрібен код-рев'ю, хоча огляд ще не є повторно використовуваним віджетом.
Коментарі (1)