@@ -301,6 +301,54 @@ impl Val {
301301 pub const fn vertical ( self ) -> UiRect {
302302 UiRect :: vertical ( self )
303303 }
304+
305+ /// Try to add two `Val`s.
306+ ///
307+ /// Returns [`ValArithmeticError::IncompatibleUnits`] if the units differ or both are `Val::Auto`.
308+ ///
309+ /// ```
310+ /// # use bevy_ui::{Val, ValArithmeticError};
311+ /// assert_eq!(Val::Px(1.).try_add(Val::Px(2.)), Ok(Val::Px(3.)));
312+ /// assert_eq!(
313+ /// Val::Px(1.).try_add(Val::Percent(2.)),
314+ /// Err(ValArithmeticError::IncompatibleUnits)
315+ /// );
316+ /// ```
317+ pub const fn try_add ( self , val : Val ) -> Result < Val , ValArithmeticError > {
318+ match ( self , val) {
319+ ( Val :: Px ( u) , Val :: Px ( v) ) => Ok ( Val :: Px ( u + v) ) ,
320+ ( Val :: Percent ( u) , Val :: Percent ( v) ) => Ok ( Val :: Percent ( u + v) ) ,
321+ ( Val :: Vw ( u) , Val :: Vw ( v) ) => Ok ( Val :: Vw ( u + v) ) ,
322+ ( Val :: Vh ( u) , Val :: Vh ( v) ) => Ok ( Val :: Vh ( u + v) ) ,
323+ ( Val :: VMin ( u) , Val :: VMin ( v) ) => Ok ( Val :: VMin ( u + v) ) ,
324+ ( Val :: VMax ( u) , Val :: VMax ( v) ) => Ok ( Val :: VMax ( u + v) ) ,
325+ _ => Err ( ValArithmeticError :: IncompatibleUnits ) ,
326+ }
327+ }
328+
329+ /// Try to subtract one `Val` from another.
330+ ///
331+ /// Returns [`ValArithmeticError::IncompatibleUnits`] if the units differ or both are `Val::Auto`.
332+ ///
333+ /// ```
334+ /// # use bevy_ui::{Val, ValArithmeticError};
335+ /// assert_eq!(Val::Px(3.).try_sub(Val::Px(2.)), Ok(Val::Px(1.)));
336+ /// assert_eq!(
337+ /// Val::Px(1.).try_sub(Val::Percent(2.)),
338+ /// Err(ValArithmeticError::IncompatibleUnits)
339+ /// );
340+ /// ```
341+ pub const fn try_sub ( self , val : Val ) -> Result < Val , ValArithmeticError > {
342+ match ( self , val) {
343+ ( Val :: Px ( u) , Val :: Px ( v) ) => Ok ( Val :: Px ( u - v) ) ,
344+ ( Val :: Percent ( u) , Val :: Percent ( v) ) => Ok ( Val :: Percent ( u - v) ) ,
345+ ( Val :: Vw ( u) , Val :: Vw ( v) ) => Ok ( Val :: Vw ( u - v) ) ,
346+ ( Val :: Vh ( u) , Val :: Vh ( v) ) => Ok ( Val :: Vh ( u - v) ) ,
347+ ( Val :: VMin ( u) , Val :: VMin ( v) ) => Ok ( Val :: VMin ( u - v) ) ,
348+ ( Val :: VMax ( u) , Val :: VMax ( v) ) => Ok ( Val :: VMax ( u - v) ) ,
349+ _ => Err ( ValArithmeticError :: IncompatibleUnits ) ,
350+ }
351+ }
304352}
305353
306354impl Default for Val {
@@ -389,6 +437,8 @@ impl Neg for Val {
389437pub enum ValArithmeticError {
390438 #[ error( "the given variant of Val is not evaluable (non-numeric)" ) ]
391439 NonEvaluable ,
440+ #[ error( "the given variants of Val have incompatible units" ) ]
441+ IncompatibleUnits ,
392442}
393443
394444impl Val {
@@ -1178,10 +1228,60 @@ mod tests {
11781228 }
11791229
11801230 #[ test]
1181- fn val_arithmetic_error_messages ( ) {
1231+ fn val_try_add_compatible_variants ( ) {
1232+ assert_eq ! ( Val :: Px ( 1. ) . try_add( Val :: Px ( 2. ) ) , Ok ( Val :: Px ( 3. ) ) ) ;
1233+ assert_eq ! (
1234+ Val :: Percent ( 1. ) . try_add( Val :: Percent ( 2. ) ) ,
1235+ Ok ( Val :: Percent ( 3. ) )
1236+ ) ;
1237+ assert_eq ! ( Val :: Vw ( 1. ) . try_add( Val :: Vw ( 2. ) ) , Ok ( Val :: Vw ( 3. ) ) ) ;
1238+ assert_eq ! ( Val :: Vh ( 1. ) . try_add( Val :: Vh ( 2. ) ) , Ok ( Val :: Vh ( 3. ) ) ) ;
1239+ assert_eq ! ( Val :: VMin ( 1. ) . try_add( Val :: VMin ( 2. ) ) , Ok ( Val :: VMin ( 3. ) ) ) ;
1240+ assert_eq ! ( Val :: VMax ( 1. ) . try_add( Val :: VMax ( 2. ) ) , Ok ( Val :: VMax ( 3. ) ) ) ;
1241+ }
1242+
1243+ #[ test]
1244+ fn val_try_add_incompatible_variants ( ) {
1245+ assert_eq ! (
1246+ Val :: Auto . try_add( Val :: Auto ) ,
1247+ Err ( ValArithmeticError :: IncompatibleUnits )
1248+ ) ;
1249+ assert_eq ! (
1250+ Val :: Px ( 1. ) . try_add( Val :: Percent ( 2. ) ) ,
1251+ Err ( ValArithmeticError :: IncompatibleUnits )
1252+ ) ;
1253+ assert_eq ! (
1254+ Val :: Auto . try_add( Val :: Px ( 1. ) ) ,
1255+ Err ( ValArithmeticError :: IncompatibleUnits )
1256+ ) ;
1257+ }
1258+
1259+ #[ test]
1260+ fn val_try_sub_compatible_variants ( ) {
1261+ assert_eq ! ( Val :: Px ( 3. ) . try_sub( Val :: Px ( 2. ) ) , Ok ( Val :: Px ( 1. ) ) ) ;
1262+ assert_eq ! (
1263+ Val :: Percent ( 3. ) . try_sub( Val :: Percent ( 2. ) ) ,
1264+ Ok ( Val :: Percent ( 1. ) )
1265+ ) ;
1266+ assert_eq ! ( Val :: Vw ( 3. ) . try_sub( Val :: Vw ( 2. ) ) , Ok ( Val :: Vw ( 1. ) ) ) ;
1267+ assert_eq ! ( Val :: Vh ( 3. ) . try_sub( Val :: Vh ( 2. ) ) , Ok ( Val :: Vh ( 1. ) ) ) ;
1268+ assert_eq ! ( Val :: VMin ( 3. ) . try_sub( Val :: VMin ( 2. ) ) , Ok ( Val :: VMin ( 1. ) ) ) ;
1269+ assert_eq ! ( Val :: VMax ( 3. ) . try_sub( Val :: VMax ( 2. ) ) , Ok ( Val :: VMax ( 1. ) ) ) ;
1270+ }
1271+
1272+ #[ test]
1273+ fn val_try_sub_incompatible_variants ( ) {
1274+ assert_eq ! (
1275+ Val :: Auto . try_sub( Val :: Auto ) ,
1276+ Err ( ValArithmeticError :: IncompatibleUnits )
1277+ ) ;
1278+ assert_eq ! (
1279+ Val :: Px ( 1. ) . try_sub( Val :: Percent ( 2. ) ) ,
1280+ Err ( ValArithmeticError :: IncompatibleUnits )
1281+ ) ;
11821282 assert_eq ! (
1183- format! ( "{}" , ValArithmeticError :: NonEvaluable ) ,
1184- "the given variant of Val is not evaluable (non-numeric)"
1283+ Val :: Auto . try_sub ( Val :: Px ( 1. ) ) ,
1284+ Err ( ValArithmeticError :: IncompatibleUnits )
11851285 ) ;
11861286 }
11871287
0 commit comments