@gjsify/adwaita-web 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adwaita-web.css +8066 -3033
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-application-window.spec.d.ts +1 -0
- package/lib/types/adw-bin.spec.d.ts +1 -0
- package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
- package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
- package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
- package/lib/types/adw-preferences-row.spec.d.ts +1 -0
- package/lib/types/adw-shortcuts.spec.d.ts +1 -0
- package/lib/types/adw-tab-bar.spec.d.ts +1 -0
- package/lib/types/adw-tab-button.spec.d.ts +1 -0
- package/lib/types/adw-tab-overview.spec.d.ts +1 -0
- package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
- package/lib/types/adw-window.spec.d.ts +1 -0
- package/lib/types/breakpoints.d.ts +14 -3
- package/lib/types/construct-vectors.spec.d.ts +1 -0
- package/lib/types/elements/adw-application-window.d.ts +27 -0
- package/lib/types/elements/adw-bin.d.ts +17 -0
- package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
- package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
- package/lib/types/elements/adw-dialog.d.ts +10 -0
- package/lib/types/elements/adw-layout-slot.d.ts +19 -0
- package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
- package/lib/types/elements/adw-preferences-row.d.ts +31 -0
- package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
- package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
- package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
- package/lib/types/elements/adw-sidebar.d.ts +5 -0
- package/lib/types/elements/adw-switch-row.d.ts +3 -0
- package/lib/types/elements/adw-tab-bar.d.ts +108 -0
- package/lib/types/elements/adw-tab-button.d.ts +32 -0
- package/lib/types/elements/adw-tab-overview.d.ts +199 -0
- package/lib/types/elements/adw-tab-view.d.ts +19 -23
- package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
- package/lib/types/elements/adw-window.d.ts +40 -0
- package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
- package/lib/types/elements/gtk-application-window.d.ts +34 -0
- package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
- package/lib/types/elements/gtk-button.d.ts +9 -0
- package/lib/types/elements/gtk-calendar.d.ts +159 -0
- package/lib/types/elements/gtk-center-box.d.ts +39 -0
- package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
- package/lib/types/elements/gtk-column-view.d.ts +50 -0
- package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
- package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
- package/lib/types/elements/gtk-editable-label.d.ts +33 -0
- package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
- package/lib/types/elements/gtk-entry.d.ts +20 -1
- package/lib/types/elements/gtk-expander.d.ts +49 -0
- package/lib/types/elements/gtk-fixed.d.ts +13 -0
- package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
- package/lib/types/elements/gtk-flow-box.d.ts +87 -0
- package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
- package/lib/types/elements/gtk-frame.d.ts +24 -0
- package/lib/types/elements/gtk-gl-area.d.ts +136 -0
- package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
- package/lib/types/elements/gtk-grid-view.d.ts +39 -0
- package/lib/types/elements/gtk-grid.d.ts +27 -0
- package/lib/types/elements/gtk-header-bar.d.ts +60 -0
- package/lib/types/elements/gtk-inscription.d.ts +64 -0
- package/lib/types/elements/gtk-label.d.ts +3 -0
- package/lib/types/elements/gtk-level-bar.d.ts +59 -0
- package/lib/types/elements/gtk-link-button.d.ts +29 -0
- package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
- package/lib/types/elements/gtk-list-box.d.ts +100 -0
- package/lib/types/elements/gtk-list-view.d.ts +73 -0
- package/lib/types/elements/gtk-media-controls.d.ts +142 -0
- package/lib/types/elements/gtk-notebook.d.ts +148 -0
- package/lib/types/elements/gtk-overlay.d.ts +22 -0
- package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
- package/lib/types/elements/gtk-paned.d.ts +121 -0
- package/lib/types/elements/gtk-password-entry.d.ts +27 -0
- package/lib/types/elements/gtk-picture.d.ts +66 -0
- package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
- package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
- package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
- package/lib/types/elements/gtk-popover.d.ts +28 -3
- package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
- package/lib/types/elements/gtk-revealer.d.ts +55 -0
- package/lib/types/elements/gtk-scale-button.d.ts +59 -0
- package/lib/types/elements/gtk-scale.d.ts +98 -0
- package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
- package/lib/types/elements/gtk-scrolled-window.d.ts +121 -0
- package/lib/types/elements/gtk-search-bar.d.ts +39 -0
- package/lib/types/elements/gtk-search-entry.d.ts +27 -0
- package/lib/types/elements/gtk-separator.d.ts +10 -0
- package/lib/types/elements/gtk-spin-button.d.ts +94 -0
- package/lib/types/elements/gtk-spinner.d.ts +14 -0
- package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
- package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
- package/lib/types/elements/gtk-stack.d.ts +154 -0
- package/lib/types/elements/gtk-switch.d.ts +4 -1
- package/lib/types/elements/gtk-text-view.d.ts +62 -0
- package/lib/types/elements/gtk-text.d.ts +45 -0
- package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
- package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
- package/lib/types/elements/gtk-video.d.ts +97 -0
- package/lib/types/elements/gtk-viewport.d.ts +84 -0
- package/lib/types/elements/gtk-window-controls.d.ts +80 -0
- package/lib/types/elements/gtk-window-handle.d.ts +39 -0
- package/lib/types/elements/gtk-window.d.ts +97 -0
- package/lib/types/elements/justification.d.ts +2 -0
- package/lib/types/elements/popover-menu.d.ts +18 -0
- package/lib/types/elements/roving-focus.d.ts +29 -1
- package/lib/types/emoji-data.d.ts +38 -0
- package/lib/types/font-description.d.ts +96 -0
- package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
- package/lib/types/gtk-action-bar.spec.d.ts +1 -0
- package/lib/types/gtk-application-window.spec.d.ts +1 -0
- package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
- package/lib/types/gtk-calendar.spec.d.ts +1 -0
- package/lib/types/gtk-center-box.spec.d.ts +1 -0
- package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
- package/lib/types/gtk-column-view.spec.d.ts +1 -0
- package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
- package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
- package/lib/types/gtk-editable-label.spec.d.ts +1 -0
- package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
- package/lib/types/gtk-expander.spec.d.ts +1 -0
- package/lib/types/gtk-fixed.spec.d.ts +1 -0
- package/lib/types/gtk-flow-box.spec.d.ts +1 -0
- package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
- package/lib/types/gtk-frame.spec.d.ts +1 -0
- package/lib/types/gtk-gl-area.spec.d.ts +1 -0
- package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
- package/lib/types/gtk-grid-view.spec.d.ts +1 -0
- package/lib/types/gtk-grid.spec.d.ts +1 -0
- package/lib/types/gtk-header-bar.spec.d.ts +1 -0
- package/lib/types/gtk-inscription.spec.d.ts +1 -0
- package/lib/types/gtk-level-bar.spec.d.ts +1 -0
- package/lib/types/gtk-link-button.spec.d.ts +1 -0
- package/lib/types/gtk-list-box.spec.d.ts +1 -0
- package/lib/types/gtk-list-view.spec.d.ts +1 -0
- package/lib/types/gtk-media-controls.spec.d.ts +1 -0
- package/lib/types/gtk-notebook.spec.d.ts +1 -0
- package/lib/types/gtk-overlay.spec.d.ts +1 -0
- package/lib/types/gtk-paned.spec.d.ts +1 -0
- package/lib/types/gtk-password-entry.spec.d.ts +1 -0
- package/lib/types/gtk-picture.spec.d.ts +1 -0
- package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
- package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
- package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
- package/lib/types/gtk-popover-role.spec.d.ts +1 -0
- package/lib/types/gtk-popover.spec.d.ts +1 -0
- package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
- package/lib/types/gtk-revealer.spec.d.ts +1 -0
- package/lib/types/gtk-scale-button.spec.d.ts +1 -0
- package/lib/types/gtk-scale.spec.d.ts +1 -0
- package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
- package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
- package/lib/types/gtk-search-bar.spec.d.ts +1 -0
- package/lib/types/gtk-search-entry.spec.d.ts +1 -0
- package/lib/types/gtk-separator.spec.d.ts +1 -0
- package/lib/types/gtk-spin-button.spec.d.ts +1 -0
- package/lib/types/gtk-spinner.spec.d.ts +1 -0
- package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
- package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
- package/lib/types/gtk-stack.spec.d.ts +1 -0
- package/lib/types/gtk-text-view.spec.d.ts +1 -0
- package/lib/types/gtk-text.spec.d.ts +1 -0
- package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
- package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
- package/lib/types/gtk-video.spec.d.ts +1 -0
- package/lib/types/gtk-viewport.spec.d.ts +1 -0
- package/lib/types/gtk-window-controls.spec.d.ts +1 -0
- package/lib/types/gtk-window-handle.spec.d.ts +1 -0
- package/lib/types/gtk-window.spec.d.ts +1 -0
- package/lib/types/index.d.ts +4 -1
- package/lib/types/list-view-dom.d.ts +44 -0
- package/lib/types/namespace/adw.d.ts +12 -0
- package/lib/types/namespace/gtk.d.ts +61 -0
- package/lib/types/page-setup.d.ts +100 -0
- package/lib/types/scroll-shading.d.ts +15 -1
- package/lib/types/shared-tree-builder.d.ts +30 -2
- package/lib/types/signals.d.ts +4 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/lib/types/tab-chip.d.ts +73 -0
- package/lib/types/template-classes.d.ts +11 -0
- package/package.json +12 -8
- package/scss/_action_row.scss +2 -2
- package/scss/_application_window.scss +26 -0
- package/scss/_aspect_frame.scss +25 -0
- package/scss/_bin.scss +26 -0
- package/scss/_button.scss +45 -0
- package/scss/_calendar.scss +176 -0
- package/scss/_center_box.scss +25 -0
- package/scss/_checks.scss +6 -1
- package/scss/_clamp_scrollable.scss +28 -0
- package/scss/_color_button.scss +67 -0
- package/scss/_column_view.scss +126 -0
- package/scss/_drag_icon.scss +55 -0
- package/scss/_drawing.scss +85 -0
- package/scss/_emoji_chooser.scss +213 -0
- package/scss/_entry.scss +13 -5
- package/scss/_entry_row.scss +1 -1
- package/scss/_expander.scss +113 -0
- package/scss/_fixed.scss +29 -0
- package/scss/_flow_box.scss +94 -0
- package/scss/_font_button.scss +63 -0
- package/scss/_frame.scss +41 -0
- package/scss/_grid.scss +19 -0
- package/scss/_grid_view.scss +46 -0
- package/scss/_gtk_about_dialog.scss +186 -0
- package/scss/_headerbar.scss +132 -0
- package/scss/_icons.generated.scss +186 -0
- package/scss/_inscription.scss +125 -0
- package/scss/_level_bar.scss +190 -0
- package/scss/_link.scss +82 -0
- package/scss/_list_box.scss +88 -0
- package/scss/_list_view.scss +96 -0
- package/scss/_media_controls.scss +139 -0
- package/scss/_overlay.scss +68 -0
- package/scss/_paned.scss +130 -0
- package/scss/_password_entry.scss +83 -0
- package/scss/_picture.scss +80 -0
- package/scss/_popover_bin.scss +53 -0
- package/scss/_popover_menu_bar.scss +104 -0
- package/scss/_preferences_row.scss +51 -0
- package/scss/_print_dialogs.scss +328 -0
- package/scss/_reset.scss +21 -19
- package/scss/_revealer.scss +37 -0
- package/scss/_row.scss +20 -5
- package/scss/_scale.scss +298 -0
- package/scss/_scale_button.scss +167 -0
- package/scss/_scrollbar.scss +230 -0
- package/scss/_scrolled_window.scss +131 -0
- package/scss/_search_bar.scss +118 -0
- package/scss/_search_entry.scss +86 -0
- package/scss/_separator.scss +44 -0
- package/scss/_shortcuts_dialog.scss +100 -0
- package/scss/_spin_button.scss +172 -0
- package/scss/_spin_row.scss +56 -8
- package/scss/_spinner.scss +85 -4
- package/scss/_stack.scss +729 -0
- package/scss/_switch.scss +13 -5
- package/scss/_switch_row.scss +10 -0
- package/scss/_tab_bar.scss +317 -0
- package/scss/_tab_button.scss +98 -0
- package/scss/_tab_overview.scss +483 -0
- package/scss/_text.scss +182 -0
- package/scss/_theme.scss +1 -1
- package/scss/_tree_expander.scss +62 -0
- package/scss/_variables.scss +1 -1
- package/scss/_video.scss +146 -0
- package/scss/_view_switcher_sidebar.scss +112 -0
- package/scss/_viewport.scss +50 -0
- package/scss/_window.scss +118 -1
- package/scss/_window_handle.scss +20 -0
- package/scss/adwaita-skin.scss +109 -0
- package/src/adw-action-rows.spec.ts +76 -0
- package/src/adw-application-window.spec.ts +118 -0
- package/src/adw-bin.spec.ts +75 -0
- package/src/adw-breakpoint-bin.spec.ts +324 -0
- package/src/adw-clamp-scrollable.spec.ts +189 -0
- package/src/adw-multi-layout-view.spec.ts +243 -0
- package/src/adw-preferences-row.spec.ts +164 -0
- package/src/adw-row-state.spec.ts +142 -0
- package/src/adw-shortcuts.spec.ts +155 -0
- package/src/adw-tab-bar.spec.ts +287 -0
- package/src/adw-tab-button.spec.ts +101 -0
- package/src/adw-tab-overview.spec.ts +443 -0
- package/src/adw-view-switcher-sidebar.spec.ts +281 -0
- package/src/adw-window.spec.ts +129 -0
- package/src/breakpoints.ts +25 -8
- package/src/capabilities.d.mts +3 -0
- package/src/capabilities.mjs +18 -0
- package/src/connect-lifecycle.spec.ts +12 -0
- package/src/construct-vectors.spec.ts +175 -0
- package/src/elements/adw-application-window.ts +154 -0
- package/src/elements/adw-bin.ts +101 -0
- package/src/elements/adw-breakpoint-bin.ts +287 -0
- package/src/elements/adw-clamp-scrollable.ts +207 -0
- package/src/elements/adw-dialog.ts +19 -0
- package/src/elements/adw-layout-slot.ts +95 -0
- package/src/elements/adw-multi-layout-view.ts +326 -0
- package/src/elements/adw-preferences-row.ts +150 -0
- package/src/elements/adw-shortcuts-dialog.ts +52 -0
- package/src/elements/adw-shortcuts-item.ts +171 -0
- package/src/elements/adw-shortcuts-section.ts +86 -0
- package/src/elements/adw-sidebar.ts +42 -3
- package/src/elements/adw-switch-row.ts +28 -1
- package/src/elements/adw-tab-bar.ts +529 -0
- package/src/elements/adw-tab-button.ts +194 -0
- package/src/elements/adw-tab-overview.ts +1011 -0
- package/src/elements/adw-tab-view.ts +66 -145
- package/src/elements/adw-toggle-group.ts +20 -5
- package/src/elements/adw-view-stack.ts +18 -0
- package/src/elements/adw-view-switcher-sidebar.ts +332 -0
- package/src/elements/adw-window.ts +185 -11
- package/src/elements/checks.ts +35 -8
- package/src/elements/gtk-about-dialog.ts +811 -0
- package/src/elements/gtk-application-window.ts +108 -0
- package/src/elements/gtk-aspect-frame.ts +160 -0
- package/src/elements/gtk-button.ts +12 -0
- package/src/elements/gtk-calendar.ts +757 -0
- package/src/elements/gtk-center-box.ts +184 -0
- package/src/elements/gtk-color-dialog-button.ts +278 -0
- package/src/elements/gtk-column-view.ts +320 -0
- package/src/elements/gtk-drag-icon.ts +257 -0
- package/src/elements/gtk-drawing-area.ts +303 -0
- package/src/elements/gtk-editable-label.ts +204 -0
- package/src/elements/gtk-emoji-chooser.ts +542 -0
- package/src/elements/gtk-entry.ts +39 -5
- package/src/elements/gtk-expander.ts +301 -0
- package/src/elements/gtk-fixed.ts +99 -0
- package/src/elements/gtk-flow-box-child.ts +68 -0
- package/src/elements/gtk-flow-box.ts +480 -0
- package/src/elements/gtk-font-dialog-button.ts +432 -0
- package/src/elements/gtk-frame.ts +174 -0
- package/src/elements/gtk-gl-area.ts +476 -0
- package/src/elements/gtk-graphics-offload.ts +130 -0
- package/src/elements/gtk-grid-view.ts +168 -0
- package/src/elements/gtk-grid.ts +127 -0
- package/src/elements/gtk-header-bar.ts +273 -0
- package/src/elements/gtk-inscription.ts +387 -0
- package/src/elements/gtk-label.ts +19 -11
- package/src/elements/gtk-level-bar.ts +323 -0
- package/src/elements/gtk-link-button.ts +138 -0
- package/src/elements/gtk-list-box-row.ts +195 -0
- package/src/elements/gtk-list-box.ts +413 -0
- package/src/elements/gtk-list-view.ts +370 -0
- package/src/elements/gtk-media-controls.ts +509 -0
- package/src/elements/gtk-notebook.ts +664 -0
- package/src/elements/gtk-overlay.ts +149 -0
- package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
- package/src/elements/gtk-paned.ts +597 -0
- package/src/elements/gtk-password-entry.ts +170 -0
- package/src/elements/gtk-picture.ts +254 -0
- package/src/elements/gtk-popover-bin.ts +332 -0
- package/src/elements/gtk-popover-menu-bar.ts +355 -0
- package/src/elements/gtk-popover-menu.ts +339 -0
- package/src/elements/gtk-popover.ts +92 -10
- package/src/elements/gtk-print-unix-dialog.ts +989 -0
- package/src/elements/gtk-progress-bar.ts +24 -11
- package/src/elements/gtk-revealer.ts +406 -0
- package/src/elements/gtk-scale-button.ts +358 -0
- package/src/elements/gtk-scale.ts +492 -0
- package/src/elements/gtk-scrollbar.ts +528 -0
- package/src/elements/gtk-scrolled-window.ts +642 -0
- package/src/elements/gtk-search-bar.ts +200 -0
- package/src/elements/gtk-search-entry.ts +172 -0
- package/src/elements/gtk-separator.ts +52 -0
- package/src/elements/gtk-spin-button.ts +475 -0
- package/src/elements/gtk-spinner.ts +126 -0
- package/src/elements/gtk-stack-sidebar.ts +212 -0
- package/src/elements/gtk-stack-switcher.ts +279 -0
- package/src/elements/gtk-stack.ts +748 -0
- package/src/elements/gtk-switch.ts +52 -19
- package/src/elements/gtk-text-view.ts +290 -0
- package/src/elements/gtk-text.ts +219 -0
- package/src/elements/gtk-toggle-button.ts +239 -0
- package/src/elements/gtk-tree-expander.ts +243 -0
- package/src/elements/gtk-video.ts +423 -0
- package/src/elements/gtk-viewport.ts +277 -0
- package/src/elements/gtk-window-controls.ts +341 -0
- package/src/elements/gtk-window-handle.ts +221 -0
- package/src/elements/gtk-window.ts +366 -0
- package/src/elements/justification.ts +24 -0
- package/src/elements/popover-menu.ts +24 -0
- package/src/elements/roving-focus.ts +53 -21
- package/src/emoji-data.ts +577 -0
- package/src/entry-rows.spec.ts +31 -0
- package/src/font-description.ts +238 -0
- package/src/gtk-about-dialog.spec.ts +250 -0
- package/src/gtk-action-bar.spec.ts +89 -0
- package/src/gtk-application-window.spec.ts +107 -0
- package/src/gtk-aspect-frame.spec.ts +114 -0
- package/src/gtk-calendar.spec.ts +589 -0
- package/src/gtk-center-box.spec.ts +125 -0
- package/src/gtk-color-dialog-button.spec.ts +141 -0
- package/src/gtk-column-view.spec.ts +154 -0
- package/src/gtk-drag-icon.spec.ts +190 -0
- package/src/gtk-drawing-area.spec.ts +211 -0
- package/src/gtk-editable-label.spec.ts +190 -0
- package/src/gtk-emoji-chooser.spec.ts +173 -0
- package/src/gtk-entry.spec.ts +23 -0
- package/src/gtk-expander.spec.ts +170 -0
- package/src/gtk-fixed.spec.ts +97 -0
- package/src/gtk-flow-box.spec.ts +289 -0
- package/src/gtk-font-dialog-button.spec.ts +166 -0
- package/src/gtk-frame.spec.ts +119 -0
- package/src/gtk-gl-area.spec.ts +361 -0
- package/src/gtk-graphics-offload.spec.ts +119 -0
- package/src/gtk-grid-view.spec.ts +106 -0
- package/src/gtk-grid.spec.ts +122 -0
- package/src/gtk-header-bar.spec.ts +202 -0
- package/src/gtk-inscription.spec.ts +235 -0
- package/src/gtk-level-bar.spec.ts +199 -0
- package/src/gtk-link-button.spec.ts +117 -0
- package/src/gtk-list-box.spec.ts +422 -0
- package/src/gtk-list-view.spec.ts +203 -0
- package/src/gtk-media-controls.spec.ts +295 -0
- package/src/gtk-notebook.spec.ts +546 -0
- package/src/gtk-overlay.spec.ts +141 -0
- package/src/gtk-paned.spec.ts +267 -0
- package/src/gtk-password-entry.spec.ts +150 -0
- package/src/gtk-picture.spec.ts +172 -0
- package/src/gtk-popover-bin.spec.ts +229 -0
- package/src/gtk-popover-menu-bar.spec.ts +296 -0
- package/src/gtk-popover-menu.spec.ts +261 -0
- package/src/gtk-popover-role.spec.ts +138 -0
- package/src/gtk-popover.spec.ts +264 -0
- package/src/gtk-print-dialogs.spec.ts +251 -0
- package/src/gtk-revealer.spec.ts +164 -0
- package/src/gtk-scale-button.spec.ts +218 -0
- package/src/gtk-scale.spec.ts +213 -0
- package/src/gtk-scrollbar.spec.ts +244 -0
- package/src/gtk-scrolled-window.spec.ts +262 -0
- package/src/gtk-search-bar.spec.ts +179 -0
- package/src/gtk-search-entry.spec.ts +142 -0
- package/src/gtk-separator.spec.ts +74 -0
- package/src/gtk-spin-button.spec.ts +186 -0
- package/src/gtk-spinner.spec.ts +130 -0
- package/src/gtk-stack-sidebar.spec.ts +217 -0
- package/src/gtk-stack-switcher.spec.ts +249 -0
- package/src/gtk-stack.spec.ts +432 -0
- package/src/gtk-text-view.spec.ts +189 -0
- package/src/gtk-text.spec.ts +163 -0
- package/src/gtk-toggle-button.spec.ts +186 -0
- package/src/gtk-tree-expander.spec.ts +201 -0
- package/src/gtk-video.spec.ts +240 -0
- package/src/gtk-viewport.spec.ts +140 -0
- package/src/gtk-window-controls.spec.ts +232 -0
- package/src/gtk-window-handle.spec.ts +158 -0
- package/src/gtk-window.spec.ts +190 -0
- package/src/index.ts +9 -1
- package/src/keyboard-operable.spec.ts +33 -1
- package/src/list-view-dom.ts +121 -0
- package/src/namespace/adw.ts +12 -0
- package/src/namespace/gtk.ts +61 -0
- package/src/page-setup.ts +222 -0
- package/src/scroll-shading.ts +18 -1
- package/src/shared-tree-builder.ts +263 -21
- package/src/signals.ts +15 -0
- package/src/style-classes.spec.ts +9 -8
- package/src/styles.generated.ts +1 -1
- package/src/tab-chip.ts +200 -0
- package/src/template-classes.ts +45 -0
- package/src/test.browser.mts +152 -0
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
// <adw-print-unix-dialog> — the browser counterpart of `GtkPrintUnixDialog`: the Unix
|
|
2
|
+
// print dialog, a notebook of General / Page Setup / Job / Image Quality / Color /
|
|
3
|
+
// Finishing / Advanced over a printer list, with the conflicts action bar and the
|
|
4
|
+
// Preview / Cancel / Print action area (gtkprintunixdialog.ui).
|
|
5
|
+
//
|
|
6
|
+
// THE REPLICA PRINTS NOTHING. A browser has no print backend, no CUPS over D-Bus and no
|
|
7
|
+
// spooler — `gtk_print_backend_load_modules` (:1274-1310) is what GTK reaches for, and
|
|
8
|
+
// none of it exists here. What this element ports is the DIALOG: its layout, its page
|
|
9
|
+
// set, and every derivation the C runs over a printer's capabilities and options. The
|
|
10
|
+
// buttons behave as GTK's do with no printer: Preview is hidden (no PREVIEW capability),
|
|
11
|
+
// Print is INSENSITIVE (`gtk_dialog_set_response_sensitive (…, GTK_RESPONSE_OK, FALSE)`
|
|
12
|
+
// is what `selected_printer_changed` :1842-1874 sets until a printer that accepts jobs is
|
|
13
|
+
// chosen), and the four option pages are the EMPTY grids the C leaves them in when
|
|
14
|
+
// `_gtk_printer_get_options` has no printer to ask.
|
|
15
|
+
//
|
|
16
|
+
// The DIALOG CHROME IS `<adw-dialog>`'s — this element extends it, so the scrim, the
|
|
17
|
+
// sheet, `present()`/`close()`, `can-close`, Escape, the Tab trap and the return-focus are
|
|
18
|
+
// the ones `adw-dialog.ts` owns, and there is no `aria-modal` below.
|
|
19
|
+
//
|
|
20
|
+
// WHAT IS PORTED FROM `gtkprintunixdialog.c`
|
|
21
|
+
//
|
|
22
|
+
// · `update_dialog_from_capabilities` (:1563-1592): every sensitive control is gated on
|
|
23
|
+
// `manual_capabilities | printer_capabilities`, `collate` additionally needs a copies
|
|
24
|
+
// count above 1 (`atoi (copies) > 1`), and the Preview button is VISIBLE — not merely
|
|
25
|
+
// insensitive — only with the PREVIEW capability;
|
|
26
|
+
// · `set_current_page` (:3059-3073): "Current Page" is sensitive only for a page that is
|
|
27
|
+
// not -1;
|
|
28
|
+
// · `set_support_selection` / `set_has_selection` (:3325-3405): the Selection radio is
|
|
29
|
+
// VISIBLE only when the application supports printing a selection, and sensitive only
|
|
30
|
+
// when it also HAS one;
|
|
31
|
+
// · `update_page_range_entry_sensitivity` (:1962-1972) and
|
|
32
|
+
// `page_range_entry_focus_changed` (:1951-1960): picking "Pages:" focuses the entry,
|
|
33
|
+
// and focusing the entry picks "Pages:";
|
|
34
|
+
// · `update_print_at_entry_sensitivity` (:1974-1989): the same pair for "At:";
|
|
35
|
+
// · `update_collate_icon` (:1920-1949): the four page thumbnails' NUMBERS depend on
|
|
36
|
+
// collate and reverse, and the second COLUMN is visible only when the copies count is
|
|
37
|
+
// above 1 — which is the one piece of the print dialog that explains itself;
|
|
38
|
+
// · `selected_printer_changed` (:1821-1915): choosing a printer that accepts jobs makes
|
|
39
|
+
// Print sensitive, and its capabilities become the second half of every gate above;
|
|
40
|
+
// · `gtk_print_unix_dialog_new` (:2961-2972): a NULL title means "Print";
|
|
41
|
+
// · `draw_page` (:2283-2681) for the Page Setup preview: the sheet scaled to
|
|
42
|
+
// `EXAMPLE_PAGE_AREA_SIZE` (110px), divided by the number-up grid — 1, 2, 4, 6, 9 or 16
|
|
43
|
+
// pages, flipping for 2 and 6 — and each cell numbered in the number-up ORDER. The
|
|
44
|
+
// ruler and its two dimension captions the C draws around it are the part not painted
|
|
45
|
+
// here: they are decoration outside the sheet, and the mm caption is on the label.
|
|
46
|
+
//
|
|
47
|
+
// Attributes (the GObject property names, hyphenated): `current-page`, `embed-page-setup`,
|
|
48
|
+
// `has-selection`, `manual-capabilities`, `support-selection`, plus `title`, `open`,
|
|
49
|
+
// `can-close`, `content-width`, `content-height`, `presentation-mode`, `show-header` from
|
|
50
|
+
// the chrome. `manual-capabilities` takes the nick SET the GIR generates, `|`-separated —
|
|
51
|
+
// `manual-capabilities="page-set|copies|collate|reverse|scale|preview"`.
|
|
52
|
+
//
|
|
53
|
+
// Properties with no attribute form: `pageSetup` and `printSettings` (`GtkPageSetup` /
|
|
54
|
+
// `GtkPrintSettings` OBJECTS, carried as the plain data `src/page-setup.ts` defines),
|
|
55
|
+
// `printerOptions` (the per-printer option widgets GTK fills from the backend — see the
|
|
56
|
+
// header), and `printers` (the list a backend would have discovered; an INPUT here).
|
|
57
|
+
// `selectedPrinter` is read-only, as in the C.
|
|
58
|
+
//
|
|
59
|
+
// Events: the base class's `notify::open` (`{ open }`) and `closed`, plus `response`
|
|
60
|
+
// (detail `{ responseId }`) — GTK_RESPONSE_APPLY (-10, "Pre_view"), GTK_RESPONSE_CANCEL
|
|
61
|
+
// (-6) and GTK_RESPONSE_OK (-5, "_Print"), the three `gtk_dialog_add_buttons` passes.
|
|
62
|
+
//
|
|
63
|
+
// A11y: role `dialog` from `AdwModalSurface`; the notebook is a tab list over `tabpanel`
|
|
64
|
+
// roles, the printer rows are radios, and every control has the label the `.ui` gives it.
|
|
65
|
+
//
|
|
66
|
+
// Reference: refs/gtk/gtk/print/gtkprintunixdialog.c (every rule above, by line)
|
|
67
|
+
// Reference: refs/gtk/gtk/print/ui/gtkprintunixdialog.ui (the notebook, the groups,
|
|
68
|
+
// the group headings, the radio labels, the action area)
|
|
69
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_dialogs.scss:9-34
|
|
70
|
+
// (`window.print:not(.ssd-frame)`: the `drawing` node, white `paper` with
|
|
71
|
+
// `background-clip: padding-box` and a 1px `$border_color` border, a FLAT titlebar and
|
|
72
|
+
// a `.view` `.dialog-action-box`)
|
|
73
|
+
// Copyright (c) 2006-2024 Red Hat, Inc. / The GTK authors. LGPLv2.1+.
|
|
74
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the page setup is
|
|
75
|
+
// the plain data of packages/web/adwaita-web/src/page-setup.ts; nothing prints.
|
|
76
|
+
|
|
77
|
+
import {
|
|
78
|
+
type PageOrientation,
|
|
79
|
+
type PageSetup,
|
|
80
|
+
COMMON_PAPER_SIZES,
|
|
81
|
+
defaultMargins,
|
|
82
|
+
defaultPageSetup,
|
|
83
|
+
orientedSize,
|
|
84
|
+
paperSizeOf,
|
|
85
|
+
} from '../page-setup.js';
|
|
86
|
+
|
|
87
|
+
import { AdwDialog } from './adw-dialog.js';
|
|
88
|
+
import { createGtkImage } from './gtk-image.js';
|
|
89
|
+
|
|
90
|
+
/** The three action-area response ids `gtk_dialog_add_buttons` passes. */
|
|
91
|
+
const RESPONSE_APPLY = -10;
|
|
92
|
+
const RESPONSE_CANCEL = -6;
|
|
93
|
+
const RESPONSE_OK = -5;
|
|
94
|
+
|
|
95
|
+
/** The `GtkPrintCapabilities` nicks, in enum order (the GIR's own spelling). */
|
|
96
|
+
const CAPABILITY_NICKS = [
|
|
97
|
+
'collate',
|
|
98
|
+
'copies',
|
|
99
|
+
'generate-pdf',
|
|
100
|
+
'generate-ps',
|
|
101
|
+
'number-up',
|
|
102
|
+
'number-up-layout',
|
|
103
|
+
'page-set',
|
|
104
|
+
'preview',
|
|
105
|
+
'reverse',
|
|
106
|
+
'scale',
|
|
107
|
+
] as const;
|
|
108
|
+
|
|
109
|
+
/** One `GtkPrintCapabilities` nick. */
|
|
110
|
+
export type PrintCapability = (typeof CAPABILITY_NICKS)[number];
|
|
111
|
+
|
|
112
|
+
/** The seven notebook tabs, in the `.ui`'s order. */
|
|
113
|
+
const TABS = ['General', 'Page Setup', 'Job', 'Image Quality', 'Color', 'Finishing', 'Advanced'] as const;
|
|
114
|
+
type PrintTab = (typeof TABS)[number];
|
|
115
|
+
|
|
116
|
+
/** `page_set_combo`'s three models, in the `.ui`'s order. */
|
|
117
|
+
const PAGE_SET_ITEMS = ['All sheets', 'Even sheets', 'Odd sheets'];
|
|
118
|
+
|
|
119
|
+
/** `orientation_combo`'s four models, in the `.ui`'s order. */
|
|
120
|
+
const ORIENTATION_ITEMS: PageOrientation[] = ['portrait', 'landscape', 'reverse-portrait', 'reverse-landscape'];
|
|
121
|
+
|
|
122
|
+
/** One row of the printer list — what `GtkPrinter` answers name / location / icon for. */
|
|
123
|
+
export interface PrinterInfo {
|
|
124
|
+
readonly name: string;
|
|
125
|
+
readonly location?: string;
|
|
126
|
+
/** The `.ui`'s icon column, from the printer's own `icon-name`. */
|
|
127
|
+
readonly iconName?: string;
|
|
128
|
+
/** `gtk_printer_is_accepting_jobs` — what gates the Print button. */
|
|
129
|
+
readonly acceptsJobs?: boolean;
|
|
130
|
+
/** `gtk_printer_get_capabilities` — the second half of every sensitivity gate. */
|
|
131
|
+
readonly capabilities?: readonly PrintCapability[];
|
|
132
|
+
/** Whether the row passes `is_printer_active` (:1164-1186). */
|
|
133
|
+
readonly active?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** The `Gtk.PrintSettings` this dialog carries, in the keys its own UI sets. */
|
|
137
|
+
export interface PrintSettingsData {
|
|
138
|
+
/** `format-for-printer` — the printer the settings belong to. */
|
|
139
|
+
readonly 'format-for-printer'?: string;
|
|
140
|
+
/** `copies` — a string, because `GtkPrintSettings` values are all strings. */
|
|
141
|
+
readonly copies?: string;
|
|
142
|
+
/** `collate` / `reverse` — `"0"` or `"1"`, as CUPS writes them. */
|
|
143
|
+
readonly collate?: string;
|
|
144
|
+
readonly reverse?: string;
|
|
145
|
+
/** `page-set` — `all` / `even` / `odd`, the index into `PAGE_SET_ITEMS`. */
|
|
146
|
+
readonly 'page-set'?: string;
|
|
147
|
+
/** `scale` — a percentage, as a string. */
|
|
148
|
+
readonly scale?: string;
|
|
149
|
+
/** `orientation` — `portrait` … `reverse-landscape`. */
|
|
150
|
+
readonly orientation?: string;
|
|
151
|
+
/** `print-at` — an ISO timestamp for the "At:" branch. */
|
|
152
|
+
readonly 'print-at'?: string;
|
|
153
|
+
/** `printer-setting-…` — the per-printer option groups of the Job tab. */
|
|
154
|
+
readonly [key: string]: string | undefined;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* `GtkPrintUnixDialog`'s default settings, from `gtk_print_unix_dialog_init` (:875-905) and
|
|
159
|
+
* `update_dialog_from_settings`: copies 1, collate and reverse off, scale 100, all sheets,
|
|
160
|
+
* portrait, and nothing scheduled.
|
|
161
|
+
*/
|
|
162
|
+
const DEFAULT_SETTINGS: PrintSettingsData = {
|
|
163
|
+
copies: '1',
|
|
164
|
+
collate: '0',
|
|
165
|
+
reverse: '0',
|
|
166
|
+
'page-set': '0',
|
|
167
|
+
scale: '100',
|
|
168
|
+
orientation: 'portrait',
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export class GtkPrintUnixDialog extends AdwDialog {
|
|
172
|
+
private _built = false;
|
|
173
|
+
private _printers: PrinterInfo[] = [];
|
|
174
|
+
private _selected: PrinterInfo | null = null;
|
|
175
|
+
private _settings: PrintSettingsData = { ...DEFAULT_SETTINGS };
|
|
176
|
+
private _pageSetup: PageSetup = defaultPageSetup();
|
|
177
|
+
private _printerListEl!: HTMLElement;
|
|
178
|
+
private _switcherEl!: HTMLDivElement;
|
|
179
|
+
private _panelEl!: HTMLElement;
|
|
180
|
+
private _tabPages = new Map<PrintTab, HTMLElement>();
|
|
181
|
+
private _tab: PrintTab = 'General';
|
|
182
|
+
private _currentPage = -1;
|
|
183
|
+
private _supportSelection = false;
|
|
184
|
+
private _hasSelection = false;
|
|
185
|
+
private _manual: Set<PrintCapability> = new Set();
|
|
186
|
+
private _range: 'all' | 'current' | 'selection' | 'pages' = 'all';
|
|
187
|
+
private _printAt: 'now' | 'at' | 'hold' = 'now';
|
|
188
|
+
private _printButton!: HTMLButtonElement;
|
|
189
|
+
private _previewButton!: HTMLButtonElement;
|
|
190
|
+
private _conflictsEl!: HTMLElement;
|
|
191
|
+
private _capabilityControls = new Map<PrintCapability, HTMLElement>();
|
|
192
|
+
private _collateCheck!: HTMLElement & { checked: boolean };
|
|
193
|
+
private _reverseCheck!: HTMLElement & { checked: boolean };
|
|
194
|
+
private _copiesInput!: HTMLInputElement;
|
|
195
|
+
private _paperDrop!: HTMLElement & { selected: number };
|
|
196
|
+
private _orientationDrop!: HTMLElement & { selected: number };
|
|
197
|
+
private _pageRangeInput!: HTMLInputElement;
|
|
198
|
+
private _selectionRadio!: HTMLElement & { checked: boolean };
|
|
199
|
+
private _currentPageRadio!: HTMLElement & { checked: boolean };
|
|
200
|
+
private _rangeRadios = new Map<string, HTMLElement & { checked: boolean }>();
|
|
201
|
+
private _atInput: HTMLInputElement | null = null;
|
|
202
|
+
|
|
203
|
+
static get observedAttributes(): string[] {
|
|
204
|
+
// The five properties the GIR declares as SCALARS (`:1589` on). `page-setup`,
|
|
205
|
+
// `print-settings` and `selected-printer` are `GtkPageSetup` / `GtkPrintSettings`
|
|
206
|
+
// / `GtkPrinter` objects, which an attribute cannot carry — they are the plain-data
|
|
207
|
+
// properties below, and `check-adwaita-element-properties.mjs` excludes them for
|
|
208
|
+
// exactly that reason.
|
|
209
|
+
return [
|
|
210
|
+
...AdwDialog.observedAttributes,
|
|
211
|
+
'current-page',
|
|
212
|
+
'embed-page-setup',
|
|
213
|
+
'has-selection',
|
|
214
|
+
'manual-capabilities',
|
|
215
|
+
'support-selection',
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ------------------------------------------------------------- properties
|
|
220
|
+
|
|
221
|
+
/** `current-page`, in 0-based document pages; -1 disables "Current Page". */
|
|
222
|
+
get currentPage(): number {
|
|
223
|
+
return this._currentPage;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
set currentPage(value: number) {
|
|
227
|
+
this._currentPage = value;
|
|
228
|
+
if (this._built) this._renderPrint();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Whether the page-setup controls are EMBEDDED rather than in their own dialog. */
|
|
232
|
+
get embedPageSetup(): boolean {
|
|
233
|
+
return this.hasAttribute('embed-page-setup');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
set embedPageSetup(value: boolean) {
|
|
237
|
+
this.toggleAttribute('embed-page-setup', value);
|
|
238
|
+
if (this._built) this._renderPrint();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Whether the application has a selection to print. */
|
|
242
|
+
get hasSelection(): boolean {
|
|
243
|
+
return this._hasSelection;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
set hasSelection(value: boolean) {
|
|
247
|
+
this._hasSelection = value;
|
|
248
|
+
if (this._built) this._renderPrint();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Whether the application supports printing a selection. */
|
|
252
|
+
get supportSelection(): boolean {
|
|
253
|
+
return this.hasAttribute('support-selection');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
set supportSelection(value: boolean) {
|
|
257
|
+
this.toggleAttribute('support-selection', value);
|
|
258
|
+
if (this._built) this._renderPrint();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** The capabilities the APPLICATION handles, as `GtkPrintCapabilities` nicks. */
|
|
262
|
+
get manualCapabilities(): PrintCapability[] {
|
|
263
|
+
return [...this._manual];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
set manualCapabilities(value: readonly PrintCapability[]) {
|
|
267
|
+
this._manual = new Set(value.filter((capability) => CAPABILITY_NICKS.includes(capability)));
|
|
268
|
+
if (this._built) this._renderPrint();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** The chosen printer, or `null` — `gtk_print_unix_dialog_get_selected_printer`. */
|
|
272
|
+
get selectedPrinter(): PrinterInfo | null {
|
|
273
|
+
return this._selected === null ? null : { ...this._selected };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** The page setup, as the plain `PageSetup` the value model defines. */
|
|
277
|
+
get pageSetup(): PageSetup {
|
|
278
|
+
return { ...this._pageSetup };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
set pageSetup(value: PageSetup) {
|
|
282
|
+
this._pageSetup = value;
|
|
283
|
+
if (this._built) this._renderPrint();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** The print settings, in the keys the dialog's own controls write. */
|
|
287
|
+
get printSettings(): PrintSettingsData {
|
|
288
|
+
return { ...this._settings };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
set printSettings(value: PrintSettingsData) {
|
|
292
|
+
this._settings = { ...DEFAULT_SETTINGS, ...value };
|
|
293
|
+
if (this._built) this._renderPrint();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Which of the four range buttons is active — the radio group the `.ui` calls the
|
|
298
|
+
* Range frame. GTK has no property for it either: the dialog READS whichever of the four
|
|
299
|
+
* `GtkCheckButton`s is active (`dialog_get_page_range`), and that is what this holds.
|
|
300
|
+
*/
|
|
301
|
+
get range(): 'all' | 'current' | 'selection' | 'pages' {
|
|
302
|
+
return this._range;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
set range(value: 'all' | 'current' | 'selection' | 'pages') {
|
|
306
|
+
this._range = value;
|
|
307
|
+
if (!this._built) return;
|
|
308
|
+
const radio = this._rangeRadios.get(value);
|
|
309
|
+
if (radio !== undefined) radio.checked = true;
|
|
310
|
+
this._renderPrint();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** The printers a print backend would have discovered. An INPUT here — see the header. */
|
|
314
|
+
get printers(): PrinterInfo[] {
|
|
315
|
+
return this._printers.map((printer) => ({ ...printer }));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
set printers(value: readonly PrinterInfo[]) {
|
|
319
|
+
this._printers = value.map((printer) => ({ ...printer }));
|
|
320
|
+
this._selected = null;
|
|
321
|
+
if (this._built) this._renderPrint();
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ------------------------------------------------------------- lifecycle
|
|
325
|
+
|
|
326
|
+
connectedCallback(): void {
|
|
327
|
+
if (this._built) {
|
|
328
|
+
super.connectedCallback();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
// BEFORE `super.connectedCallback()`, which renders and therefore calls
|
|
332
|
+
// `decorateHeader` — the tab switcher is what that hook installs, as with
|
|
333
|
+
// `<gtk-about-dialog>`.
|
|
334
|
+
this._switcherEl = document.createElement('div');
|
|
335
|
+
this._switcherEl.className = 'adw-print-switcher';
|
|
336
|
+
this._switcherEl.setAttribute('role', 'tablist');
|
|
337
|
+
super.connectedCallback();
|
|
338
|
+
|
|
339
|
+
// `gtk_print_unix_dialog_new`: a NULL title means "Print".
|
|
340
|
+
if (!this.hasAttribute('title')) this.setAttribute('title', 'Print');
|
|
341
|
+
this._readManual();
|
|
342
|
+
|
|
343
|
+
// The base adopts the author's light-DOM children into `contentArea` on
|
|
344
|
+
// connect; rebuilding around them must keep them, AFTER the dialog's own UI —
|
|
345
|
+
// which is also where children appended later land (`slotted-children.spec.ts`
|
|
346
|
+
// pins the equality, path and index).
|
|
347
|
+
const adopted = [...this.contentArea.childNodes];
|
|
348
|
+
this.contentArea.replaceChildren(this._build());
|
|
349
|
+
for (const node of adopted) this.contentArea.appendChild(node);
|
|
350
|
+
this._renderPrint();
|
|
351
|
+
// `_built` goes last: either `setAttribute` above re-enters through
|
|
352
|
+
// `attributeChangedCallback`, and rendering a half-built dialog throws.
|
|
353
|
+
this._built = true;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {
|
|
357
|
+
super.attributeChangedCallback(name, oldValue, newValue);
|
|
358
|
+
if (!this._built || oldValue === newValue) return;
|
|
359
|
+
if (name === 'title') return;
|
|
360
|
+
if (name === 'manual-capabilities') this._readManual();
|
|
361
|
+
this._renderPrint();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* `manual-capabilities` takes the nick SET the GIR generates, `|`-separated —
|
|
366
|
+
* `manual-capabilities="page-set|copies|collate|reverse|scale|preview"`. Unknown
|
|
367
|
+
* nicks are dropped, which is what the GIR-validated setter does with them.
|
|
368
|
+
*/
|
|
369
|
+
private _readManual(): void {
|
|
370
|
+
this._manual = new Set(
|
|
371
|
+
(this.getAttribute('manual-capabilities') ?? '')
|
|
372
|
+
.split('|')
|
|
373
|
+
.map((nick) => nick.trim())
|
|
374
|
+
.filter((nick) => CAPABILITY_NICKS.includes(nick as PrintCapability)) as PrintCapability[],
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
protected override decorateHeader(header: HTMLElement): void {
|
|
379
|
+
const title = header.querySelector('.adw-dialog-title');
|
|
380
|
+
if (title !== null) title.replaceWith(this._switcherEl);
|
|
381
|
+
else header.prepend(this._switcherEl);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ------------------------------------------------------------- building
|
|
385
|
+
|
|
386
|
+
private _build(): HTMLElement {
|
|
387
|
+
const root = document.createElement('div');
|
|
388
|
+
root.className = 'adw-print-root';
|
|
389
|
+
|
|
390
|
+
this._panelEl = document.createElement('div');
|
|
391
|
+
this._panelEl.className = 'adw-print-panel';
|
|
392
|
+
this._panelEl.setAttribute('role', 'tabpanel');
|
|
393
|
+
|
|
394
|
+
root.append(this._panelEl, this._buildConflicts(), this._buildActions());
|
|
395
|
+
this._renderPanel();
|
|
396
|
+
return root;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Every page of the notebook, built once and hidden but for the visible one —
|
|
401
|
+
* which is what `GtkNotebook` holds: all seven pages exist whether shown or not,
|
|
402
|
+
* so the capability pass can reach every control from the first render.
|
|
403
|
+
*/
|
|
404
|
+
private _renderPanel(): void {
|
|
405
|
+
for (const tab of TABS) {
|
|
406
|
+
let page = this._tabPages.get(tab);
|
|
407
|
+
if (page === undefined) {
|
|
408
|
+
page = document.createElement('div');
|
|
409
|
+
page.className = 'adw-print-page';
|
|
410
|
+
page.setAttribute('role', 'tabpanel');
|
|
411
|
+
page.dataset.tab = tab;
|
|
412
|
+
page.appendChild(this._buildTab(tab));
|
|
413
|
+
this._tabPages.set(tab, page);
|
|
414
|
+
this._panelEl.appendChild(page);
|
|
415
|
+
}
|
|
416
|
+
page.hidden = tab !== this._tab;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private _buildTab(tab: PrintTab): HTMLElement {
|
|
421
|
+
switch (tab) {
|
|
422
|
+
case 'General':
|
|
423
|
+
return this._buildGeneral();
|
|
424
|
+
case 'Page Setup':
|
|
425
|
+
return this._buildPageSetup();
|
|
426
|
+
case 'Job':
|
|
427
|
+
return this._buildJob();
|
|
428
|
+
// The four option pages: a scrolled grid the backend's `GtkPrinterOptionWidget`s
|
|
429
|
+
// go into. With no backend there are none, so they are the EMPTY grids the C
|
|
430
|
+
// leaves them in — the headings above them are what tells the reader why.
|
|
431
|
+
case 'Image Quality':
|
|
432
|
+
case 'Color':
|
|
433
|
+
case 'Finishing':
|
|
434
|
+
return this._buildOptionsPage(tab);
|
|
435
|
+
case 'Advanced':
|
|
436
|
+
return this._buildOptionsPage(tab);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** General: the printer list, then Range and Copies. */
|
|
441
|
+
private _buildGeneral(): HTMLElement {
|
|
442
|
+
const box = document.createElement('div');
|
|
443
|
+
box.className = 'adw-print-columns';
|
|
444
|
+
|
|
445
|
+
this._printerListEl = document.createElement('div');
|
|
446
|
+
this._printerListEl.className = 'adw-print-printer-list';
|
|
447
|
+
this._printerListEl.setAttribute('role', 'radiogroup');
|
|
448
|
+
this._printerListEl.setAttribute('aria-label', 'Printer');
|
|
449
|
+
box.appendChild(this._frame(this._printerListEl));
|
|
450
|
+
|
|
451
|
+
const right = document.createElement('div');
|
|
452
|
+
right.className = 'adw-print-column';
|
|
453
|
+
|
|
454
|
+
// Range
|
|
455
|
+
const rangeGroup = this._group('Range');
|
|
456
|
+
const range = rangeGroup.body;
|
|
457
|
+
for (const [value, label] of [
|
|
458
|
+
['all', 'All Pages'],
|
|
459
|
+
['current', 'Current Page'],
|
|
460
|
+
['selection', 'Selection'],
|
|
461
|
+
] as Array<['all' | 'current' | 'selection', string]>) {
|
|
462
|
+
const radio = this._radio(label, `adw-print-range-${value}`);
|
|
463
|
+
radio.addEventListener('notify::checked', () => {
|
|
464
|
+
if (radio.checked) {
|
|
465
|
+
this._range = value;
|
|
466
|
+
if (value === 'current' || value === 'selection') this._renderPrint();
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
if (value === 'current') this._currentPageRadio = radio;
|
|
470
|
+
if (value === 'selection') this._selectionRadio = radio;
|
|
471
|
+
this._rangeRadios.set(value, radio);
|
|
472
|
+
range.appendChild(radio);
|
|
473
|
+
}
|
|
474
|
+
const pagesRadio = this._radio('Pages:', 'adw-print-range-pages');
|
|
475
|
+
pagesRadio.addEventListener('notify::checked', () => {
|
|
476
|
+
if (!pagesRadio.checked) return;
|
|
477
|
+
this._range = 'pages';
|
|
478
|
+
// `update_page_range_entry_sensitivity`: picking "Pages:" grabs the entry.
|
|
479
|
+
this._pageRangeInput.focus();
|
|
480
|
+
});
|
|
481
|
+
this._pageRangeInput = document.createElement('input');
|
|
482
|
+
this._pageRangeInput.type = 'text';
|
|
483
|
+
this._pageRangeInput.className = 'adw-print-page-range-entry';
|
|
484
|
+
this._pageRangeInput.title = 'Specify one or more page ranges, e.g. 1–3, 7, 11';
|
|
485
|
+
this._pageRangeInput.setAttribute('aria-label', 'Pages');
|
|
486
|
+
// `page_range_entry_focus_changed`: focusing the entry picks its radio.
|
|
487
|
+
this._pageRangeInput.addEventListener('focus', () => {
|
|
488
|
+
this._range = 'pages';
|
|
489
|
+
pagesRadio.checked = true;
|
|
490
|
+
});
|
|
491
|
+
this._rangeRadios.set('pages', pagesRadio);
|
|
492
|
+
const pagesRow = document.createElement('div');
|
|
493
|
+
pagesRow.className = 'adw-print-grid-row';
|
|
494
|
+
pagesRow.append(pagesRadio, this._pageRangeInput);
|
|
495
|
+
range.appendChild(pagesRow);
|
|
496
|
+
right.appendChild(rangeGroup.group);
|
|
497
|
+
|
|
498
|
+
// Copies
|
|
499
|
+
const copiesGroup = this._group('Copies');
|
|
500
|
+
const copies = copiesGroup.body;
|
|
501
|
+
const copiesRow = document.createElement('div');
|
|
502
|
+
copiesRow.className = 'adw-print-grid-row';
|
|
503
|
+
const copiesLabel = document.createElement('div');
|
|
504
|
+
copiesLabel.className = 'adw-print-label';
|
|
505
|
+
copiesLabel.textContent = 'Copies:';
|
|
506
|
+
this._copiesInput = document.createElement('input');
|
|
507
|
+
this._copiesInput.type = 'number';
|
|
508
|
+
this._copiesInput.min = '1';
|
|
509
|
+
this._copiesInput.className = 'adw-print-copies';
|
|
510
|
+
this._copiesInput.value = this._settings.copies ?? '1';
|
|
511
|
+
this._copiesInput.setAttribute('aria-label', 'Copies');
|
|
512
|
+
// `copies_spin`'s `changed` and `value-changed` both run the capability pass.
|
|
513
|
+
this._copiesInput.addEventListener('input', () => {
|
|
514
|
+
this._settings = { ...this._settings, copies: this._copiesInput.value };
|
|
515
|
+
this._renderPrint();
|
|
516
|
+
});
|
|
517
|
+
copiesRow.append(copiesLabel, this._copiesInput);
|
|
518
|
+
copies.appendChild(copiesRow);
|
|
519
|
+
|
|
520
|
+
this._collateCheck = this._check('Collate', 'adw-print-collate');
|
|
521
|
+
this._reverseCheck = this._check('Reverse', 'adw-print-reverse');
|
|
522
|
+
for (const check of [this._collateCheck, this._reverseCheck]) {
|
|
523
|
+
check.addEventListener('notify::checked', () => this._renderPrint());
|
|
524
|
+
}
|
|
525
|
+
copies.append(this._collateCheck, this._reverseCheck);
|
|
526
|
+
|
|
527
|
+
const preview = this._buildCollatePreview();
|
|
528
|
+
const previewRow = document.createElement('div');
|
|
529
|
+
previewRow.className = 'adw-print-grid-row';
|
|
530
|
+
previewRow.appendChild(preview);
|
|
531
|
+
copies.appendChild(previewRow);
|
|
532
|
+
right.appendChild(copiesGroup.group);
|
|
533
|
+
|
|
534
|
+
box.appendChild(right);
|
|
535
|
+
return box;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/** `page_collate_preview`: four thumbnails whose NUMBERS show the ordering. */
|
|
539
|
+
private _buildCollatePreview(): HTMLElement {
|
|
540
|
+
const preview = document.createElement('div');
|
|
541
|
+
preview.className = 'adw-print-collate-preview';
|
|
542
|
+
preview.setAttribute('role', 'img');
|
|
543
|
+
preview.setAttribute(
|
|
544
|
+
'aria-label',
|
|
545
|
+
'A visualization of the effect of the collate and reverse options on the page ordering',
|
|
546
|
+
);
|
|
547
|
+
preview.dataset.columnA = '2';
|
|
548
|
+
preview.dataset.columnB = '1';
|
|
549
|
+
return preview;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** Page Setup: Layout and Paper beside the sheet preview. */
|
|
553
|
+
private _buildPageSetup(): HTMLElement {
|
|
554
|
+
const box = document.createElement('div');
|
|
555
|
+
box.className = 'adw-print-columns';
|
|
556
|
+
|
|
557
|
+
const left = document.createElement('div');
|
|
558
|
+
left.className = 'adw-print-column';
|
|
559
|
+
|
|
560
|
+
// Layout
|
|
561
|
+
const layoutGroup = this._group('Layout');
|
|
562
|
+
const layout = layoutGroup.body;
|
|
563
|
+
// `page_set_combo` is the one Layout control `update_dialog_from_capabilities`
|
|
564
|
+
// gates (PAGE_SET); the scale input below is gated by SCALE.
|
|
565
|
+
layout.appendChild(this._labelledRow('Two-sided:', this._dropDown(PAGE_SET_ITEMS, 'Two-sided')));
|
|
566
|
+
const scaleInput = document.createElement('input');
|
|
567
|
+
scaleInput.type = 'number';
|
|
568
|
+
scaleInput.min = '10';
|
|
569
|
+
scaleInput.max = '400';
|
|
570
|
+
scaleInput.className = 'adw-print-scale';
|
|
571
|
+
scaleInput.value = this._settings.scale ?? '100';
|
|
572
|
+
scaleInput.setAttribute('aria-label', 'Scale in percent');
|
|
573
|
+
scaleInput.addEventListener('input', () => {
|
|
574
|
+
this._settings = { ...this._settings, scale: scaleInput.value };
|
|
575
|
+
this._renderPrint();
|
|
576
|
+
});
|
|
577
|
+
this._capabilityControls.set('scale', scaleInput);
|
|
578
|
+
const scaleRow = document.createElement('div');
|
|
579
|
+
scaleRow.className = 'adw-print-grid-row';
|
|
580
|
+
const scaleLabel = document.createElement('div');
|
|
581
|
+
scaleLabel.className = 'adw-print-label';
|
|
582
|
+
scaleLabel.textContent = 'Scale:';
|
|
583
|
+
const percent = document.createElement('span');
|
|
584
|
+
percent.className = 'adw-print-label';
|
|
585
|
+
percent.textContent = '%';
|
|
586
|
+
scaleRow.append(scaleLabel, scaleInput, percent);
|
|
587
|
+
layout.appendChild(scaleRow);
|
|
588
|
+
left.appendChild(layoutGroup.group);
|
|
589
|
+
|
|
590
|
+
// Paper. BOTH drop downs are insensitive until `embed-page-setup` is set —
|
|
591
|
+
// `gtk_print_unix_dialog_set_embed_page_setup` (:3415-3427) is what connects their
|
|
592
|
+
// `notify::selected` handlers AND makes them sensitive, in that order.
|
|
593
|
+
const paperGroup = this._group('Paper');
|
|
594
|
+
const paper = paperGroup.body;
|
|
595
|
+
const paperNames = COMMON_PAPER_SIZES.map((size) => size.displayName);
|
|
596
|
+
this._paperDrop = this._dropDown(paperNames, 'Paper size');
|
|
597
|
+
this._orientationDrop = this._dropDown(
|
|
598
|
+
ORIENTATION_ITEMS.map((orientation) => orientation[0]!.toUpperCase() + orientation.slice(1)),
|
|
599
|
+
'Orientation',
|
|
600
|
+
);
|
|
601
|
+
paper.appendChild(this._labelledRow('Paper size:', this._paperDrop));
|
|
602
|
+
paper.appendChild(this._labelledRow('Orientation:', this._orientationDrop));
|
|
603
|
+
left.appendChild(paperGroup.group);
|
|
604
|
+
|
|
605
|
+
// The two drop downs react ONLY while the page setup is embedded, which is the
|
|
606
|
+
// other half of `set_embed_page_setup`: connecting a listener and making the
|
|
607
|
+
// control sensitive are one decision there.
|
|
608
|
+
this._paperDrop.addEventListener('notify::selected', () => {
|
|
609
|
+
if (!this.embedPageSetup) return;
|
|
610
|
+
this._paperChanged(this._paperDrop.selected);
|
|
611
|
+
});
|
|
612
|
+
this._orientationDrop.addEventListener('notify::selected', () => {
|
|
613
|
+
if (!this.embedPageSetup) return;
|
|
614
|
+
const orientation = ORIENTATION_ITEMS[this._orientationDrop.selected] ?? 'portrait';
|
|
615
|
+
this._pageSetup = { ...this._pageSetup, orientation };
|
|
616
|
+
this._settings = { ...this._settings, orientation };
|
|
617
|
+
this._renderPrint();
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
box.append(left, this._buildSheetPreview());
|
|
621
|
+
return box;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* `page_layout_preview` (:2683) + `draw_page` (:2283): the sheet at 110px on its long
|
|
626
|
+
* edge, divided by the number-up grid with each cell numbered in the number-up order.
|
|
627
|
+
* The ruler the C draws around it is decoration outside the sheet and is not painted.
|
|
628
|
+
*/
|
|
629
|
+
private _buildSheetPreview(): HTMLElement {
|
|
630
|
+
const preview = document.createElement('div');
|
|
631
|
+
preview.className = 'adw-print-sheet-preview';
|
|
632
|
+
preview.setAttribute('role', 'img');
|
|
633
|
+
preview.setAttribute('aria-label', 'Page layout preview');
|
|
634
|
+
const paper = document.createElement('div');
|
|
635
|
+
paper.className = 'adw-print-paper';
|
|
636
|
+
const size = paperSizeOf(this._pageSetup);
|
|
637
|
+
const landscape =
|
|
638
|
+
this._pageSetup.orientation === 'landscape' || this._pageSetup.orientation === 'reverse-landscape';
|
|
639
|
+
paper.style.aspectRatio = landscape ? `${size.height} / ${size.width}` : `${size.width} / ${size.height}`;
|
|
640
|
+
const grid = document.createElement('div');
|
|
641
|
+
grid.className = 'adw-print-number-up';
|
|
642
|
+
grid.dataset.cells = '1';
|
|
643
|
+
paper.appendChild(grid);
|
|
644
|
+
preview.appendChild(paper);
|
|
645
|
+
const caption = document.createElement('div');
|
|
646
|
+
caption.className = 'adw-print-sheet-caption';
|
|
647
|
+
caption.textContent = `${orientedSize(this._pageSetup).width.toFixed(1)} mm × ${orientedSize(this._pageSetup).height.toFixed(1)} mm`;
|
|
648
|
+
preview.appendChild(caption);
|
|
649
|
+
return preview;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** Job: Job Details, Print Document, Add Cover Page. */
|
|
653
|
+
private _buildJob(): HTMLElement {
|
|
654
|
+
const box = document.createElement('div');
|
|
655
|
+
box.className = 'adw-print-column';
|
|
656
|
+
|
|
657
|
+
// Job Details — the two printer option widgets the C puts here (`job_prio`,
|
|
658
|
+
// `billing_info`), which exist only for a printer that offers them.
|
|
659
|
+
const detailsGroup = this._group('Job Details');
|
|
660
|
+
detailsGroup.body.appendChild(this._optionsGrid('Job Details'));
|
|
661
|
+
|
|
662
|
+
const documentGroup = this._group('Print Document');
|
|
663
|
+
const document_ = documentGroup.body;
|
|
664
|
+
for (const [value, label] of [
|
|
665
|
+
['now', 'Now'],
|
|
666
|
+
['at', 'At:'],
|
|
667
|
+
['hold', 'On hold'],
|
|
668
|
+
] as Array<['now' | 'at' | 'hold', string]>) {
|
|
669
|
+
const radio = this._radio(label, 'adw-print-at');
|
|
670
|
+
radio.addEventListener('notify::checked', () => {
|
|
671
|
+
if (!radio.checked) return;
|
|
672
|
+
this._printAt = value;
|
|
673
|
+
// `update_print_at_entry_sensitivity`: the entry follows its radio, and
|
|
674
|
+
// picking "At:" grabs it.
|
|
675
|
+
if (this._atInput !== null) this._atInput.disabled = value !== 'at';
|
|
676
|
+
if (value === 'at') this._atInput?.focus();
|
|
677
|
+
});
|
|
678
|
+
document_.appendChild(radio);
|
|
679
|
+
if (value === 'at') {
|
|
680
|
+
this._atInput = document.createElement('input');
|
|
681
|
+
this._atInput.type = 'text';
|
|
682
|
+
this._atInput.className = 'adw-print-at-entry';
|
|
683
|
+
this._atInput.setAttribute('aria-label', 'Print at');
|
|
684
|
+
this._atInput.disabled = true;
|
|
685
|
+
this._atInput.addEventListener('input', () => {
|
|
686
|
+
this._settings = { ...this._settings, 'print-at': this._atInput!.value };
|
|
687
|
+
});
|
|
688
|
+
const row = document.createElement('div');
|
|
689
|
+
row.className = 'adw-print-grid-row';
|
|
690
|
+
row.appendChild(this._atInput);
|
|
691
|
+
document_.appendChild(row);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const coverGroup = this._group('Add Cover Page');
|
|
696
|
+
coverGroup.body.appendChild(this._optionsGrid('Cover Page'));
|
|
697
|
+
|
|
698
|
+
box.append(detailsGroup.group, documentGroup.group, coverGroup.group);
|
|
699
|
+
return box;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* One of the four option pages: the scrolled viewport + grid the C's
|
|
704
|
+
* `GtkPrinterOptionWidget`s are added to. There are none without a backend, so the grid
|
|
705
|
+
* is empty and says so rather than inventing options.
|
|
706
|
+
*/
|
|
707
|
+
private _buildOptionsPage(tab: PrintTab): HTMLElement {
|
|
708
|
+
const box = document.createElement('div');
|
|
709
|
+
box.className = 'adw-print-column';
|
|
710
|
+
const grid = this._optionsGrid(tab);
|
|
711
|
+
if (tab === 'Advanced') {
|
|
712
|
+
// The Advanced page is a plain box (`advanced_vbox`), not a grid.
|
|
713
|
+
const advanced = document.createElement('div');
|
|
714
|
+
advanced.className = 'adw-print-advanced';
|
|
715
|
+
advanced.appendChild(grid);
|
|
716
|
+
box.appendChild(advanced);
|
|
717
|
+
return box;
|
|
718
|
+
}
|
|
719
|
+
box.appendChild(grid);
|
|
720
|
+
return box;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/** The option grid, one row per option group the backend would offer. */
|
|
724
|
+
private _optionsGrid(label: string): HTMLElement {
|
|
725
|
+
const grid = document.createElement('div');
|
|
726
|
+
grid.className = 'adw-print-options-grid';
|
|
727
|
+
grid.setAttribute('role', 'group');
|
|
728
|
+
grid.setAttribute('aria-label', label);
|
|
729
|
+
grid.dataset.empty = 'true';
|
|
730
|
+
return grid;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/** The conflicts action bar — hidden until `mark_conflicts` finds one (:3050-3060). */
|
|
734
|
+
private _buildConflicts(): HTMLElement {
|
|
735
|
+
this._conflictsEl = document.createElement('div');
|
|
736
|
+
this._conflictsEl.className = 'adw-print-conflicts';
|
|
737
|
+
this._conflictsEl.hidden = true;
|
|
738
|
+
this._conflictsEl.append(
|
|
739
|
+
createGtkImage('dialog-warning', 'adw-print-conflicts-icon'),
|
|
740
|
+
(() => {
|
|
741
|
+
const label = document.createElement('span');
|
|
742
|
+
label.className = 'adw-print-conflicts-label';
|
|
743
|
+
label.textContent = 'Some of the settings in the dialog conflict';
|
|
744
|
+
return label;
|
|
745
|
+
})(),
|
|
746
|
+
);
|
|
747
|
+
return this._conflictsEl;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/** Preview / Cancel / Print, in the `.ui`'s order and with its own response ids. */
|
|
751
|
+
private _buildActions(): HTMLElement {
|
|
752
|
+
const actions = document.createElement('div');
|
|
753
|
+
actions.className = 'adw-print-actions';
|
|
754
|
+
|
|
755
|
+
this._previewButton = document.createElement('button');
|
|
756
|
+
this._previewButton.type = 'button';
|
|
757
|
+
this._previewButton.className = 'adw-print-preview';
|
|
758
|
+
this._previewButton.textContent = 'Preview';
|
|
759
|
+
this._previewButton.addEventListener('click', () => this._respond(RESPONSE_APPLY));
|
|
760
|
+
|
|
761
|
+
const cancel = document.createElement('button');
|
|
762
|
+
cancel.type = 'button';
|
|
763
|
+
cancel.className = 'adw-print-cancel';
|
|
764
|
+
cancel.textContent = 'Cancel';
|
|
765
|
+
cancel.addEventListener('click', () => this._respond(RESPONSE_CANCEL));
|
|
766
|
+
|
|
767
|
+
this._printButton = document.createElement('button');
|
|
768
|
+
this._printButton.type = 'button';
|
|
769
|
+
this._printButton.className = 'adw-print-print suggested-action';
|
|
770
|
+
this._printButton.textContent = 'Print';
|
|
771
|
+
this._printButton.addEventListener('click', () => this._respond(RESPONSE_OK));
|
|
772
|
+
|
|
773
|
+
actions.append(this._previewButton, cancel, this._printButton);
|
|
774
|
+
return actions;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
private _respond(responseId: number): void {
|
|
778
|
+
this.dispatchEvent(new CustomEvent('response', { bubbles: true, detail: { responseId } }));
|
|
779
|
+
if (responseId !== RESPONSE_OK) this.close();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// ------------------------------------------------------------- fragments
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* One `frame_templateN`: a BOLD heading over a grid, which is the shape every group in
|
|
786
|
+
* the `.ui` has — `box > box > grid` with the heading's `weight=bold`.
|
|
787
|
+
*/
|
|
788
|
+
private _group(title: string): { group: HTMLElement; body: HTMLElement } {
|
|
789
|
+
const group = document.createElement('div');
|
|
790
|
+
group.className = 'adw-print-group';
|
|
791
|
+
const heading = document.createElement('div');
|
|
792
|
+
heading.className = 'adw-print-group-title';
|
|
793
|
+
heading.textContent = title;
|
|
794
|
+
const body = document.createElement('div');
|
|
795
|
+
body.className = 'adw-print-group-body';
|
|
796
|
+
group.append(heading, body);
|
|
797
|
+
return { group, body };
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
private _labelledRow(label: string, control: HTMLElement, capability?: PrintCapability): HTMLElement {
|
|
801
|
+
const row = document.createElement('div');
|
|
802
|
+
row.className = 'adw-print-grid-row';
|
|
803
|
+
const text = document.createElement('div');
|
|
804
|
+
text.className = 'adw-print-label';
|
|
805
|
+
text.textContent = label;
|
|
806
|
+
row.append(text, control);
|
|
807
|
+
if (capability !== undefined) this._capabilityControls.set(capability, control);
|
|
808
|
+
return row;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
private _dropDown(items: readonly string[], label: string): HTMLElement & { selected: number } {
|
|
812
|
+
const dropdown = document.createElement('gtk-drop-down') as HTMLElement & { selected: number };
|
|
813
|
+
dropdown.className = 'adw-print-dropdown';
|
|
814
|
+
dropdown.setAttribute('model', JSON.stringify([...items]));
|
|
815
|
+
dropdown.setAttribute('aria-label', label);
|
|
816
|
+
return dropdown;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private _radio(label: string, name: string): HTMLElement & { checked: boolean } {
|
|
820
|
+
const radio = document.createElement('adw-radio') as HTMLElement & { checked: boolean };
|
|
821
|
+
// The name is the class too, so the Range radios answer to
|
|
822
|
+
// `.adw-print-range-selection` and `.adw-print-range-current`.
|
|
823
|
+
radio.className = name;
|
|
824
|
+
radio.setAttribute('label', label);
|
|
825
|
+
radio.setAttribute('name', name);
|
|
826
|
+
radio.setAttribute('value', label);
|
|
827
|
+
return radio;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private _check(label: string, name: string): HTMLElement & { checked: boolean } {
|
|
831
|
+
const check = document.createElement('gtk-check-button') as HTMLElement & { checked: boolean };
|
|
832
|
+
// The name is the class too, so Collate and Reverse answer to
|
|
833
|
+
// `.adw-print-collate` and `.adw-print-reverse`.
|
|
834
|
+
check.className = name;
|
|
835
|
+
check.setAttribute('label', label);
|
|
836
|
+
check.setAttribute('name', name);
|
|
837
|
+
return check;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
private _frame(content: HTMLElement): HTMLElement {
|
|
841
|
+
const frame = document.createElement('div');
|
|
842
|
+
frame.className = 'adw-print-frame';
|
|
843
|
+
frame.appendChild(content);
|
|
844
|
+
return frame;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// ------------------------------------------------------------- rendering
|
|
848
|
+
|
|
849
|
+
/** `selected_printer_changed` (:1821-1915) — the list and what selecting does. */
|
|
850
|
+
private _printerChanged(selected: PrinterInfo | null): void {
|
|
851
|
+
this._selected = selected;
|
|
852
|
+
if (selected !== null) {
|
|
853
|
+
// The printer's capabilities replace the previous printer's (:1874), and the
|
|
854
|
+
// settings follow the printer when no explicit page setup was set.
|
|
855
|
+
this._settings = { ...this._settings, 'format-for-printer': selected.name };
|
|
856
|
+
}
|
|
857
|
+
this._renderPrint();
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
private _paperChanged(index: number): void {
|
|
861
|
+
const size = COMMON_PAPER_SIZES[index];
|
|
862
|
+
if (size === undefined) return;
|
|
863
|
+
this._pageSetup = { ...this._pageSetup, paperSize: size.name, margins: defaultMargins(size) };
|
|
864
|
+
this._renderPrint();
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/** Every capability the dialog currently has: the manual half OR the printer's. */
|
|
868
|
+
private _capabilities(): Set<PrintCapability> {
|
|
869
|
+
const capabilities = new Set(this._manual);
|
|
870
|
+
for (const capability of this._selected?.capabilities ?? []) capabilities.add(capability);
|
|
871
|
+
return capabilities;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/** `update_dialog_from_capabilities` (:1563-1592), every line of it. */
|
|
875
|
+
private _renderPrint(): void {
|
|
876
|
+
const capabilities = this._capabilities();
|
|
877
|
+
this._switcherEl.replaceChildren(
|
|
878
|
+
...TABS.map((tab) => {
|
|
879
|
+
const button = document.createElement('button');
|
|
880
|
+
button.type = 'button';
|
|
881
|
+
button.className = 'adw-print-switcher-item';
|
|
882
|
+
button.setAttribute('role', 'tab');
|
|
883
|
+
button.textContent = tab;
|
|
884
|
+
button.classList.toggle('checked', tab === this._tab);
|
|
885
|
+
button.setAttribute('aria-selected', String(tab === this._tab));
|
|
886
|
+
button.addEventListener('click', () => {
|
|
887
|
+
this._tab = tab;
|
|
888
|
+
this._renderPanel();
|
|
889
|
+
this._renderPrint();
|
|
890
|
+
});
|
|
891
|
+
return button;
|
|
892
|
+
}),
|
|
893
|
+
);
|
|
894
|
+
|
|
895
|
+
this._printerListEl.replaceChildren(
|
|
896
|
+
...this._printers.map((printer) => {
|
|
897
|
+
const row = document.createElement('button');
|
|
898
|
+
row.type = 'button';
|
|
899
|
+
row.className = 'adw-print-printer-row';
|
|
900
|
+
row.setAttribute('role', 'radio');
|
|
901
|
+
row.setAttribute('aria-checked', String(printer === this._selected));
|
|
902
|
+
row.classList.toggle('checked', printer === this._selected);
|
|
903
|
+
// The `.ui`'s icon column reads each printer's OWN `icon-name`; the
|
|
904
|
+
// default for one that has none is the printer glyph.
|
|
905
|
+
row.appendChild(
|
|
906
|
+
printer.iconName === undefined
|
|
907
|
+
? createGtkImage('printer', 'adw-print-printer-icon')
|
|
908
|
+
: createGtkImage(printer.iconName, 'adw-print-printer-icon'),
|
|
909
|
+
);
|
|
910
|
+
const text = document.createElement('span');
|
|
911
|
+
text.className = 'adw-print-printer-text';
|
|
912
|
+
const name = document.createElement('span');
|
|
913
|
+
name.className = 'adw-print-printer-name';
|
|
914
|
+
name.textContent = printer.name;
|
|
915
|
+
text.appendChild(name);
|
|
916
|
+
if (printer.location !== undefined) {
|
|
917
|
+
const location = document.createElement('span');
|
|
918
|
+
location.className = 'adw-print-printer-location';
|
|
919
|
+
location.textContent = printer.location;
|
|
920
|
+
text.appendChild(location);
|
|
921
|
+
}
|
|
922
|
+
row.appendChild(text);
|
|
923
|
+
row.addEventListener('click', () => this._printerChanged(printer));
|
|
924
|
+
return row;
|
|
925
|
+
}),
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
// `set_support_selection` (:3325-3343) then `set_has_selection` (:3369-3389): the
|
|
929
|
+
// radio is VISIBLE only with support, and sensitive only with support AND a
|
|
930
|
+
// selection. Both run in that order, so the insensitive case wins.
|
|
931
|
+
this._selectionRadio.hidden = !this.supportSelection;
|
|
932
|
+
this._selectionRadio.classList.toggle('insensitive', !this.supportSelection || !this._hasSelection);
|
|
933
|
+
this._selectionRadio.setAttribute('aria-disabled', String(!this.supportSelection || !this._hasSelection));
|
|
934
|
+
|
|
935
|
+
// `set_current_page` (:3059-3073).
|
|
936
|
+
this._currentPageRadio.classList.toggle('insensitive', this._currentPage === -1);
|
|
937
|
+
this._currentPageRadio.setAttribute('aria-disabled', String(this._currentPage === -1));
|
|
938
|
+
|
|
939
|
+
for (const [capability, control] of this._capabilityControls) {
|
|
940
|
+
control.toggleAttribute('disabled', !capabilities.has(capability));
|
|
941
|
+
}
|
|
942
|
+
// `can_collate` is `*copies != '\0' && atoi (copies) > 1` (:1570-1571).
|
|
943
|
+
const copies = Number.parseInt(this._copiesInput.value, 10);
|
|
944
|
+
const canCollate = this._copiesInput.value !== '' && Number.isFinite(copies) && copies > 1;
|
|
945
|
+
this._collateCheck.toggleAttribute('disabled', !canCollate || !capabilities.has('collate'));
|
|
946
|
+
this._reverseCheck.toggleAttribute('disabled', !capabilities.has('reverse'));
|
|
947
|
+
this._copiesInput.toggleAttribute('disabled', !capabilities.has('copies'));
|
|
948
|
+
// `set_embed_page_setup` (:3425-3426) is the ONLY thing that makes these two
|
|
949
|
+
// sensitive; with it FALSE they keep the `.ui`'s `sensitive=0` and their handlers
|
|
950
|
+
// are not connected, so a selection cannot reach the page setup.
|
|
951
|
+
this._paperDrop.toggleAttribute('disabled', !this.embedPageSetup);
|
|
952
|
+
this._orientationDrop.toggleAttribute('disabled', !this.embedPageSetup);
|
|
953
|
+
|
|
954
|
+
// `update_collate_icon` (:1920-1949): the numbers, and the second column's
|
|
955
|
+
// visibility, which is the copies count and nothing else.
|
|
956
|
+
const collate = this._collateCheck.checked;
|
|
957
|
+
const reverse = this._reverseCheck.checked;
|
|
958
|
+
const preview = this.contentArea.querySelector<HTMLElement>('.adw-print-collate-preview');
|
|
959
|
+
if (preview !== null) {
|
|
960
|
+
preview.dataset.columnA = String(collate ? (reverse ? 1 : 2) : reverse ? 2 : 1);
|
|
961
|
+
preview.dataset.columnB = String(collate ? (reverse ? 2 : 1) : reverse ? 1 : 2);
|
|
962
|
+
preview.dataset.secondColumn = String(canCollate);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Print is sensitive only for a printer that accepts jobs (:1842-1876), and Preview
|
|
966
|
+
// is VISIBLE only with the PREVIEW capability (:1587-1588).
|
|
967
|
+
const prints = this._selected !== null && (this._selected.acceptsJobs ?? true);
|
|
968
|
+
this._printButton.toggleAttribute('disabled', !prints);
|
|
969
|
+
this._previewButton.hidden = !capabilities.has('preview');
|
|
970
|
+
|
|
971
|
+
// The sheet preview follows the page setup and the two-sided pages per sheet.
|
|
972
|
+
const paper = this.contentArea.querySelector<HTMLElement>('.adw-print-paper');
|
|
973
|
+
if (paper !== null) {
|
|
974
|
+
const size = paperSizeOf(this._pageSetup);
|
|
975
|
+
const reverseLandscape = this._pageSetup.orientation === 'reverse-portrait';
|
|
976
|
+
paper.style.aspectRatio = `${
|
|
977
|
+
this._pageSetup.orientation === 'landscape' || reverseLandscape
|
|
978
|
+
? `${size.height} / ${size.width}`
|
|
979
|
+
: `${size.width} / ${size.height}`
|
|
980
|
+
}`;
|
|
981
|
+
}
|
|
982
|
+
const grid = this.contentArea.querySelector<HTMLElement>('.adw-print-number-up');
|
|
983
|
+
if (grid !== null) grid.dataset.cells = '1';
|
|
984
|
+
|
|
985
|
+
this._conflictsEl.hidden = true;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
customElements.define('gtk-print-unix-dialog', GtkPrintUnixDialog);
|