| @@ -34,8 +34,14 @@ | ||
| 34 | 34 | |
| 35 | 35 | /** First render of a window. Runs the app's `mount` hook, if any. */ |
| 36 | 36 | const ACTION_MOUNT = 'mount'; |
| 37 | 37 | |
| 38 | + /** | |
| 39 | + * The reopen lifecycle action — an open window asked to open | |
| 40 | + * again, from a URL naming another of its tabs. | |
| 41 | + */ | |
| 42 | + const ACTION_REOPEN = 'reopen'; | |
| 43 | + | |
| 38 | 44 | /** Built-in: the client changed a bound key; nothing to run, just re-render. */ |
| 39 | 45 | const ACTION_SET = 'set'; |
| 40 | 46 | |
| 41 | 47 | /** |
| @@ -101,11 +107,23 @@ | ||
| 101 | 107 | $app->id(), |
| 102 | 108 | $view |
| 103 | 109 | ); |
| 104 | 110 | |
| 111 | + // A window that declares a menu lands on the tab the opener | |
| 112 | + // asked for — the dock row that was picked — on the first | |
| 113 | + // render and again whenever it is reopened from another row. | |
| 114 | + // Generic, so no app has to remember to wire it. | |
| 115 | + if ( self::ACTION_MOUNT === $action || self::ACTION_REOPEN === $action ) { | |
| 116 | + self::apply_menu_tab( $app, $state, $os ); | |
| 117 | + } | |
| 118 | + | |
| 105 | 119 | try { |
| 106 | 120 | if ( self::ACTION_MOUNT === $action ) { |
| 107 | 121 | $app->run_mount( $state, $os ); |
| 122 | + } elseif ( self::ACTION_REOPEN === $action && ! $app->has_action( $action ) ) { | |
| 123 | + // The tab above WAS the reopen. An app that wants more | |
| 124 | + // declares the action and gets it as well. | |
| 125 | + $state->get( 'tab' ); | |
| 108 | 126 | } elseif ( self::ACTION_SET === $action ) { |
| 109 | 127 | // State already carries the bound value. |
| 110 | 128 | $app->run_action( self::ACTION_SET, $state, $os, $args, false ); |
| 111 | 129 | } elseif ( $app->has_action( $action ) ) { |
| @@ -186,8 +204,40 @@ | ||
| 186 | 204 | 'data' => $data, |
| 187 | 205 | 'tabs' => $tabs, |
| 188 | 206 | 'effects' => $os->effects->all(), |
| 189 | 207 | ); |
| 208 | + } | |
| 209 | + | |
| 210 | + /** | |
| 211 | + * Land on the tab the opener named. | |
| 212 | + * | |
| 213 | + * The dock's rows for a window that declares a menu carry | |
| 214 | + * `os_tab=<id>`, which the shell passes as the window's `tab` | |
| 215 | + * open-time param. An id the window does not have is ignored | |
| 216 | + * rather than corrected: the value comes from a URL, and a | |
| 217 | + * window landing somewhere unexpected is worse than one landing | |
| 218 | + * where it always does. | |
| 219 | + * | |
| 220 | + * @param App $app The app. | |
| 221 | + * @param State $state State to write to. | |
| 222 | + * @param Os $os Host handle, carrying the params. | |
| 223 | + * @return void | |
| 224 | + */ | |
| 225 | + private static function apply_menu_tab( App $app, State $state, Os $os ) { | |
| 226 | + $tabs = $app->menu_tabs(); | |
| 227 | + if ( ! $tabs ) { | |
| 228 | + return; | |
| 229 | + } | |
| 230 | + $wanted = (string) $os->param( 'tab', '' ); | |
| 231 | + if ( '' === $wanted ) { | |
| 232 | + return; | |
| 233 | + } | |
| 234 | + foreach ( $tabs as $tab ) { | |
| 235 | + if ( $tab['id'] === $wanted ) { | |
| 236 | + $state->set( 'tab', $wanted ); | |
| 237 | + return; | |
| 238 | + } | |
| 239 | + } | |
| 190 | 240 | } |
| 191 | 241 | |
| 192 | 242 | /** |
| 193 | 243 | * Shape a failure. |