1+ use anyhow:: Context ;
12use iced:: widget:: {
23 Column , Container , Row , Scrollable , button, image:: FilterMethod , scrollable:: Scrollbar ,
34} ;
@@ -14,7 +15,7 @@ use crate::{
1415 api:: { ResponseStream , run_server_streaming_mapped} ,
1516 decoration:: DecorationId ,
1617 layer:: LayerId ,
17- util:: convert:: FromApi ,
18+ util:: convert:: { FromApi , TryFromApi } ,
1819 widget:: { MouseAreaEvent , TextInputEvent , ViewFn , WidgetEvent , WidgetId } ,
1920} ;
2021
@@ -848,11 +849,14 @@ pub fn widget_def_to_fn(def: WidgetDef) -> Option<ViewFn> {
848849 }
849850
850851 if let Some ( style) = style. clone ( ) {
852+ use crate :: widget:: text_input:: { Style , Styles } ;
853+
854+ let style = Styles :: from_api ( style) ;
851855 let style = move |theme : & iced:: Theme , status| {
852856 use iced:: widget:: text_input;
853- let mut s = <iced:: Theme as text_input:: Catalog >:: default ( ) ( theme, status) ;
857+ let s = <iced:: Theme as text_input:: Catalog >:: default ( ) ( theme, status) ;
854858
855- let widget :: v1 :: text_input:: Style {
859+ let crate :: widget :: text_input:: Styles {
856860 active,
857861 hovered,
858862 focused,
@@ -864,37 +868,34 @@ pub fn widget_def_to_fn(def: WidgetDef) -> Option<ViewFn> {
864868 text_input:: Status :: Active => active,
865869 text_input:: Status :: Hovered => hovered. or ( active) ,
866870 text_input:: Status :: Focused { is_hovered } => {
867- let inner =
871+ let hover =
868872 if is_hovered { hover_focused. or ( hovered) } else { None } ;
869873
870- inner . or ( focused) . or ( active)
874+ hover . or ( focused) . or ( active)
871875 }
872876 text_input:: Status :: Disabled => disabled,
873877 } ;
874878
875- if let Some ( style) = inner {
876- if let Some ( background) = style. background {
877- s. background = FromApi :: from_api ( background) ;
878- }
879- if let Some ( border) = style. border {
880- s. border = FromApi :: from_api ( border) ;
881- }
882-
883- if let Some ( icon) = style. icon {
884- s. icon = FromApi :: from_api ( icon) ;
885- }
886- if let Some ( placeholder) = style. placeholder {
887- s. placeholder = FromApi :: from_api ( placeholder) ;
888- }
889- if let Some ( value) = style. value {
890- s. value = FromApi :: from_api ( value) ;
891- }
892- if let Some ( selection) = style. selection {
893- s. selection = FromApi :: from_api ( selection) ;
879+ if let Some ( Style {
880+ background,
881+ border,
882+ icon,
883+ placeholder,
884+ value,
885+ selection,
886+ } ) = inner
887+ {
888+ iced:: widget:: text_input:: Style {
889+ background : background. unwrap_or ( s. background ) ,
890+ border : border. unwrap_or ( s. border ) ,
891+ icon : icon. unwrap_or ( s. icon ) ,
892+ placeholder : placeholder. unwrap_or ( s. placeholder ) ,
893+ value : value. unwrap_or ( s. value ) ,
894+ selection : selection. unwrap_or ( s. selection ) ,
894895 }
896+ } else {
897+ s
895898 }
896-
897- s
898899 } ;
899900
900901 text_input = text_input. style ( style) ;
@@ -1259,34 +1260,50 @@ impl FromApi<widget::v1::LineHeight> for iced::widget::text::LineHeight {
12591260 fn from_api ( api_type : widget:: v1:: LineHeight ) -> Self {
12601261 use widget:: v1:: line_height:: LineHeight ;
12611262
1262- let line_height = api_type
1263- . line_height
1264- . expect ( "LineHeight should not be empty" ) ;
1265-
1266- match line_height {
1263+ let line_height = api_type. line_height . map ( |lh| match lh {
12671264 LineHeight :: Relative ( v) => Self :: Relative ( v) ,
12681265 LineHeight :: Absolute ( v) => Self :: Absolute ( v. into ( ) ) ,
1266+ } ) ;
1267+
1268+ if line_height. is_none ( ) {
1269+ tracing:: warn!( "Invalid snowcap.widget.v1.LineHeight. Using default value" ) ;
12691270 }
1271+
1272+ line_height. unwrap_or_default ( )
12701273 }
12711274}
12721275
1273- impl FromApi < widget:: v1:: Background > for iced:: Background {
1274- fn from_api ( api_type : widget:: v1:: Background ) -> Self {
1276+ impl TryFromApi < widget:: v1:: Background > for iced:: Background {
1277+ type Error = anyhow:: Error ;
1278+
1279+ fn try_from_api ( api_type : widget:: v1:: Background ) -> Result < Self , Self :: Error > {
12751280 use widget:: v1:: background:: Background ;
12761281
1277- let background = api_type. background . expect ( "Background should not be empty" ) ;
1282+ const MESSAGE : & str = "snowcap.widget.v1.Background" ;
1283+ const FIELD : & str = "background" ;
12781284
1279- match background {
1280- Background :: Color ( color) => Self :: Color ( iced:: Color :: from_api ( color) ) ,
1281- Background :: Gradient ( gradient) => Self :: Gradient ( iced:: Gradient :: from_api ( gradient) ) ,
1282- }
1285+ let Some ( background) = api_type. background else {
1286+ anyhow:: bail!( "While converting {MESSAGE}: missing field 'FIELD'" )
1287+ } ;
1288+
1289+ let background = match background {
1290+ Background :: Color ( color) => Ok ( Self :: Color ( iced:: Color :: from_api ( color) ) ) ,
1291+ Background :: Gradient ( gradient) => {
1292+ iced:: Gradient :: try_from_api ( gradient) . map ( Self :: Gradient )
1293+ }
1294+ } ;
1295+
1296+ background. with_context ( || format ! ( "While converting {MESSAGE}.{FIELD}" ) )
12831297 }
12841298}
12851299
1286- impl FromApi < widget:: v1:: Gradient > for iced:: Gradient {
1287- fn from_api ( api_type : widget:: v1:: Gradient ) -> Self {
1300+ impl TryFromApi < widget:: v1:: Gradient > for iced:: Gradient {
1301+ type Error = anyhow:: Error ;
1302+ fn try_from_api ( api_type : widget:: v1:: Gradient ) -> Result < Self , Self :: Error > {
12881303 use widget:: v1:: gradient:: { Gradient , Linear } ;
1289- let gradient = api_type. gradient . expect ( "Gradient should not be empty" ) ;
1304+ let Some ( gradient) = api_type. gradient else {
1305+ anyhow:: bail!( "Missing field 'gradient'" )
1306+ } ;
12901307
12911308 match gradient {
12921309 Gradient :: Linear ( Linear { radians, stops } ) => {
@@ -1298,8 +1315,66 @@ impl FromApi<widget::v1::Gradient> for iced::Gradient {
12981315 }
12991316 } ) ) ;
13001317
1301- iced:: Gradient :: Linear ( lin)
1318+ Ok ( iced:: Gradient :: Linear ( lin) )
13021319 }
13031320 }
13041321 }
13051322}
1323+
1324+ impl FromApi < widget:: v1:: text_input:: Style > for crate :: widget:: text_input:: Styles {
1325+ fn from_api ( api_type : widget:: v1:: text_input:: Style ) -> Self {
1326+ use crate :: widget:: text_input:: Style ;
1327+ use widget:: v1:: text_input:: style:: Inner ;
1328+
1329+ fn convert_inner ( name : & str , inner : widget:: v1:: text_input:: style:: Inner ) -> Style {
1330+ let Inner {
1331+ background,
1332+ border,
1333+ icon,
1334+ placeholder,
1335+ value,
1336+ selection,
1337+ } = inner;
1338+
1339+ let background = if let Some ( background) = background {
1340+ let from_api = TryFromApi :: try_from_api ( background) . with_context ( || {
1341+ format ! ( "While converting 'snowcap.widget.v1.text_input.Style.{name}'" )
1342+ } ) ;
1343+ match from_api {
1344+ Err ( e) => {
1345+ tracing:: error!( "{e:?}" ) ;
1346+ None
1347+ }
1348+ Ok ( b) => Some ( b) ,
1349+ }
1350+ } else {
1351+ None
1352+ } ;
1353+
1354+ Style {
1355+ background,
1356+ border : border. map ( FromApi :: from_api) ,
1357+ icon : icon. map ( FromApi :: from_api) ,
1358+ placeholder : placeholder. map ( FromApi :: from_api) ,
1359+ value : value. map ( FromApi :: from_api) ,
1360+ selection : selection. map ( FromApi :: from_api) ,
1361+ }
1362+ }
1363+
1364+ let widget:: v1:: text_input:: Style {
1365+ active,
1366+ hovered,
1367+ focused,
1368+ hover_focused,
1369+ disabled,
1370+ } = api_type;
1371+
1372+ Self {
1373+ active : active. map ( |inner| convert_inner ( "active" , inner) ) ,
1374+ hovered : hovered. map ( |inner| convert_inner ( "hovered" , inner) ) ,
1375+ focused : focused. map ( |inner| convert_inner ( "focused" , inner) ) ,
1376+ hover_focused : hover_focused. map ( |inner| convert_inner ( "hover_focused" , inner) ) ,
1377+ disabled : disabled. map ( |inner| convert_inner ( "disabled" , inner) ) ,
1378+ }
1379+ }
1380+ }
0 commit comments