// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT import { Palette } from "std-widgets.slint"; import { WindowInfo, WindowInfoHelper } from "./ui_utils.slint"; import { StackView, StackPage } from "./controls/stackview.slint"; import { CityListView } from "./city_weather.slint"; import { CityWeather } from "./weather_datatypes.slint"; import { LocationSearchView } from "./location_search.slint"; import { GeoLocation } from "./location_datatypes.slint"; import { AppPalette, AppFonts, AppImages } from "./style/styles.slint"; import { FloatingTextButton } from "./controls/generic.slint"; import { BusyLayerController, BusyLayer } from "./controls/busy-layer.slint"; // Re export for native rust export { WindowInfo, AppPalette, BusyLayerController, CityWeather, GeoLocation } component EdgeFloatingTextButton inherits FloatingTextButton { out property edge-spacing: 15px; } component AnimatedStackPage inherits StackPage { // is-active and is-opened are not set as a binding here, only when the value is actually changed. // This is to avoid redundant reevaluation of dependent properties and conditional elements. // see: https://github.com/slint-ui/slint/issues/5209 out property is-active: false; out property is-opened: false; // using a helper int property to be able to use animate property is-active-value: 0; property animation-duration: 250ms; visible: root.is-active; init => { root.is-active = (self.is-active_value == 1); } changed is-active-value => { root.is-active = (self.is-active_value == 1); } states [ active when self.is-current: { is-active-value: 1; out { animate is-active-value { delay: root.animation-duration; } } } ] content := Rectangle { changed y => { // First open animation is not working properly without the line below. (A bug?) // Seems the animation in transition is using old values, // and accessing the property somehow forces the update. self.y; if (root.is-opened != (self.y == 0)) { root.is-opened = (self.y == 0); } } y: root.is-current ? 0px : root.height; animate y { duration: root.animation-duration; easing: ease-in-out-quad; } @children } } enum PageType { Main, AddLocation, } export component AppWindow inherits Window { background: AppPalette.background; default-font-size: AppFonts.default-font-size; preferred-width: 900px; preferred-height: 600px; WindowInfoHelper { init => { // no support for the different modes currently // this is to display slint badge in proper colors Palette.color-scheme = ColorScheme.dark; } } stack := StackView { function show-page(pageType : PageType) { if (pageType == PageType.Main) { self.current-index = 0; } else if (pageType == PageType.AddLocation) { self.current-index = 1; } } function back-to-main() { self.show-page(PageType.Main); } current-index: 0; min-index: 0; StackPage { is-current: self.check-is-current(stack.current-index); init => { self.page-index = stack.insert-page(); } visible: self.page-index <= stack.current-index; CityListView {} // right (refresh) button EdgeFloatingTextButton { x: parent.width - self.width - self.edge-spacing; y: parent.height - self.height - self.edge-spacing; icon-source: AppImages.refresh; clicked => { BusyLayerController.set-busy(); CityWeather.refresh-all(); } } // left (add) button EdgeFloatingTextButton { x: self.edge-spacing; y: parent.height - self.height - self.edge-spacing; visible: CityWeather.can-add-city; icon-source: AppImages.plus; clicked => { stack.show-page(PageType.AddLocation); } } } AnimatedStackPage { is-current: self.check-is-current(stack.current-index); init => { self.page-index = stack.insert-page(); } location-search-view := LocationSearchView { property is-active: parent.is-active; property is-opened: parent.is-opened; changed is-active => { if (self.is-active) { self.clear(); } } changed is-opened => { if (self.is-opened) { self.focus(); } } close-request => { self.clear-focus(); stack.back-to-main(); } EdgeFloatingTextButton { x: parent.width - self.width - self.edge-spacing; y: parent.height - self.height - self.edge-spacing; icon-source: AppImages.xmark; clicked => { location-search-view.close-request(); } } } } } if BusyLayerController.is-busy: BusyLayer {} }