1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.tv.material3 18 19 import androidx.annotation.FloatRange 20 import androidx.compose.foundation.interaction.Interaction 21 import androidx.compose.runtime.Immutable 22 import androidx.compose.ui.graphics.Color 23 import androidx.compose.ui.graphics.Shape 24 25 /** Defines [Shape] for all TV [Interaction] states of a Clickable Surface. */ 26 @Immutable 27 class ClickableSurfaceShape 28 internal constructor( 29 internal val shape: Shape, 30 internal val focusedShape: Shape, 31 internal val pressedShape: Shape, 32 internal val disabledShape: Shape, 33 internal val focusedDisabledShape: Shape 34 ) { equalsnull35 override fun equals(other: Any?): Boolean { 36 if (this === other) return true 37 if (other == null || this::class != other::class) return false 38 39 other as ClickableSurfaceShape 40 41 if (shape != other.shape) return false 42 if (focusedShape != other.focusedShape) return false 43 if (pressedShape != other.pressedShape) return false 44 if (disabledShape != other.disabledShape) return false 45 if (focusedDisabledShape != other.focusedDisabledShape) return false 46 47 return true 48 } 49 hashCodenull50 override fun hashCode(): Int { 51 var result = shape.hashCode() 52 result = 31 * result + focusedShape.hashCode() 53 result = 31 * result + pressedShape.hashCode() 54 result = 31 * result + disabledShape.hashCode() 55 result = 31 * result + focusedDisabledShape.hashCode() 56 57 return result 58 } 59 toStringnull60 override fun toString(): String { 61 return "ClickableSurfaceShape(shape=$shape, focusedShape=$focusedShape, " + 62 "pressedShape=$pressedShape, disabledShape=$disabledShape, " + 63 "focusedDisabledShape=$focusedDisabledShape)" 64 } 65 } 66 67 /** Defines [Shape] for all TV [Interaction] states of a selectable Surface. */ 68 @Immutable 69 class SelectableSurfaceShape 70 internal constructor( 71 internal val shape: Shape, 72 internal val focusedShape: Shape, 73 internal val pressedShape: Shape, 74 internal val selectedShape: Shape, 75 internal val disabledShape: Shape, 76 internal val focusedSelectedShape: Shape, 77 internal val focusedDisabledShape: Shape, 78 internal val pressedSelectedShape: Shape, 79 internal val selectedDisabledShape: Shape, 80 internal val focusedSelectedDisabledShape: Shape 81 ) { equalsnull82 override fun equals(other: Any?): Boolean { 83 if (this === other) return true 84 if (other == null || this::class != other::class) return false 85 86 other as SelectableSurfaceShape 87 88 if (shape != other.shape) return false 89 if (focusedShape != other.focusedShape) return false 90 if (pressedShape != other.pressedShape) return false 91 if (selectedShape != other.selectedShape) return false 92 if (disabledShape != other.disabledShape) return false 93 if (focusedSelectedShape != other.focusedSelectedShape) return false 94 if (focusedDisabledShape != other.focusedDisabledShape) return false 95 if (pressedSelectedShape != other.pressedSelectedShape) return false 96 if (selectedDisabledShape != other.selectedDisabledShape) return false 97 if (focusedSelectedDisabledShape != other.focusedSelectedDisabledShape) return false 98 99 return true 100 } 101 hashCodenull102 override fun hashCode(): Int { 103 var result = shape.hashCode() 104 result = 31 * result + focusedShape.hashCode() 105 result = 31 * result + pressedShape.hashCode() 106 result = 31 * result + selectedShape.hashCode() 107 result = 31 * result + disabledShape.hashCode() 108 result = 31 * result + focusedSelectedShape.hashCode() 109 result = 31 * result + focusedDisabledShape.hashCode() 110 result = 31 * result + pressedSelectedShape.hashCode() 111 result = 31 * result + selectedDisabledShape.hashCode() 112 result = 31 * result + focusedSelectedDisabledShape.hashCode() 113 114 return result 115 } 116 toStringnull117 override fun toString(): String { 118 return "SelectableSurfaceShape(shape=$shape, focusedShape=$focusedShape," + 119 "pressedShape=$pressedShape, selectedShape=$selectedShape," + 120 "disabledShape=$disabledShape, focusedSelectedShape=$focusedSelectedShape, " + 121 "focusedDisabledShape=$focusedDisabledShape," + 122 "pressedSelectedShape=$pressedSelectedShape, " + 123 "selectedDisabledShape=$selectedDisabledShape, " + 124 "focusedSelectedDisabledShape=$focusedSelectedDisabledShape)" 125 } 126 } 127 128 /** Defines [Color] for all TV [Interaction] states of a Clickable Surface. */ 129 @Immutable 130 class ClickableSurfaceColors 131 internal constructor( 132 internal val containerColor: Color, 133 internal val contentColor: Color, 134 internal val focusedContainerColor: Color, 135 internal val focusedContentColor: Color, 136 internal val pressedContainerColor: Color, 137 internal val pressedContentColor: Color, 138 internal val disabledContainerColor: Color, 139 internal val disabledContentColor: Color 140 ) { equalsnull141 override fun equals(other: Any?): Boolean { 142 if (this === other) return true 143 if (other == null || this::class != other::class) return false 144 145 other as ClickableSurfaceColors 146 147 if (containerColor != other.containerColor) return false 148 if (contentColor != other.contentColor) return false 149 if (focusedContainerColor != other.focusedContainerColor) return false 150 if (focusedContentColor != other.focusedContentColor) return false 151 if (pressedContainerColor != other.pressedContainerColor) return false 152 if (pressedContentColor != other.pressedContentColor) return false 153 if (disabledContainerColor != other.disabledContainerColor) return false 154 if (disabledContentColor != other.disabledContentColor) return false 155 156 return true 157 } 158 hashCodenull159 override fun hashCode(): Int { 160 var result = containerColor.hashCode() 161 result = 31 * result + contentColor.hashCode() 162 result = 31 * result + focusedContainerColor.hashCode() 163 result = 31 * result + focusedContentColor.hashCode() 164 result = 31 * result + pressedContainerColor.hashCode() 165 result = 31 * result + pressedContentColor.hashCode() 166 result = 31 * result + disabledContainerColor.hashCode() 167 result = 31 * result + disabledContentColor.hashCode() 168 return result 169 } 170 toStringnull171 override fun toString(): String { 172 return "ClickableSurfaceColors(" + 173 "containerColor=$containerColor, " + 174 "contentColor=$contentColor, " + 175 "focusedContainerColor=$focusedContainerColor, " + 176 "focusedContentColor=$focusedContentColor, " + 177 "pressedContainerColor=$pressedContainerColor, " + 178 "pressedContentColor=$pressedContentColor, " + 179 "disabledContainerColor=$disabledContainerColor, " + 180 "disabledContentColor=$disabledContentColor)" 181 } 182 } 183 184 /** Defines [Color] for all TV [Interaction] states of a selectable Surface. */ 185 @Immutable 186 class SelectableSurfaceColors 187 internal constructor( 188 internal val containerColor: Color, 189 internal val contentColor: Color, 190 internal val focusedContainerColor: Color, 191 internal val focusedContentColor: Color, 192 internal val pressedContainerColor: Color, 193 internal val pressedContentColor: Color, 194 internal val selectedContainerColor: Color, 195 internal val selectedContentColor: Color, 196 internal val disabledContainerColor: Color, 197 internal val disabledContentColor: Color, 198 internal val focusedSelectedContainerColor: Color, 199 internal val focusedSelectedContentColor: Color, 200 internal val pressedSelectedContainerColor: Color, 201 internal val pressedSelectedContentColor: Color 202 ) { equalsnull203 override fun equals(other: Any?): Boolean { 204 if (this === other) return true 205 if (other == null || this::class != other::class) return false 206 207 other as SelectableSurfaceColors 208 209 if (containerColor != other.containerColor) return false 210 if (contentColor != other.contentColor) return false 211 if (focusedContainerColor != other.focusedContainerColor) return false 212 if (focusedContentColor != other.focusedContentColor) return false 213 if (pressedContainerColor != other.pressedContainerColor) return false 214 if (pressedContentColor != other.pressedContentColor) return false 215 if (selectedContainerColor != other.selectedContainerColor) return false 216 if (selectedContentColor != other.selectedContentColor) return false 217 if (disabledContainerColor != other.disabledContainerColor) return false 218 if (disabledContentColor != other.disabledContentColor) return false 219 if (focusedSelectedContainerColor != other.focusedSelectedContainerColor) return false 220 if (focusedSelectedContentColor != other.focusedSelectedContentColor) return false 221 if (pressedSelectedContainerColor != other.pressedSelectedContainerColor) return false 222 if (pressedSelectedContentColor != other.pressedSelectedContentColor) return false 223 224 return true 225 } 226 hashCodenull227 override fun hashCode(): Int { 228 var result = containerColor.hashCode() 229 result = 31 * result + contentColor.hashCode() 230 result = 31 * result + focusedContainerColor.hashCode() 231 result = 31 * result + focusedContentColor.hashCode() 232 result = 31 * result + pressedContainerColor.hashCode() 233 result = 31 * result + pressedContentColor.hashCode() 234 result = 31 * result + selectedContainerColor.hashCode() 235 result = 31 * result + selectedContentColor.hashCode() 236 result = 31 * result + disabledContainerColor.hashCode() 237 result = 31 * result + disabledContentColor.hashCode() 238 result = 31 * result + focusedSelectedContainerColor.hashCode() 239 result = 31 * result + focusedSelectedContentColor.hashCode() 240 result = 31 * result + pressedSelectedContainerColor.hashCode() 241 result = 31 * result + pressedSelectedContentColor.hashCode() 242 return result 243 } 244 toStringnull245 override fun toString(): String { 246 return "SelectableSurfaceColors(" + 247 "containerColor=$containerColor, " + 248 "contentColor=$contentColor, " + 249 "focusedContainerColor=$focusedContainerColor, " + 250 "focusedContentColor=$focusedContentColor, " + 251 "pressedContainerColor=$pressedContainerColor, " + 252 "pressedContentColor=$pressedContentColor, " + 253 "selectedContainerColor=$selectedContainerColor, " + 254 "selectedContentColor=$selectedContentColor, " + 255 "disabledContainerColor=$disabledContainerColor, " + 256 "disabledContentColor=$disabledContentColor, " + 257 "focusedSelectedContainerColor=$focusedSelectedContainerColor, " + 258 "focusedSelectedContentColor=$focusedSelectedContentColor, " + 259 "pressedSelectedContainerColor=$pressedSelectedContainerColor, " + 260 "pressedSelectedContentColor=$pressedSelectedContentColor)" 261 } 262 } 263 264 /** 265 * Defines the scale for all TV indication states of Surface. Note: This scale must be a 266 * non-negative float. 267 */ 268 @Immutable 269 class ClickableSurfaceScale 270 internal constructor( 271 @FloatRange(from = 0.0) internal val scale: Float, 272 @FloatRange(from = 0.0) internal val focusedScale: Float, 273 @FloatRange(from = 0.0) internal val pressedScale: Float, 274 @FloatRange(from = 0.0) internal val disabledScale: Float, 275 @FloatRange(from = 0.0) internal val focusedDisabledScale: Float 276 ) { equalsnull277 override fun equals(other: Any?): Boolean { 278 if (this === other) return true 279 if (other == null || this::class != other::class) return false 280 281 other as ClickableSurfaceScale 282 283 if (scale != other.scale) return false 284 if (focusedScale != other.focusedScale) return false 285 if (pressedScale != other.pressedScale) return false 286 if (disabledScale != other.disabledScale) return false 287 if (focusedDisabledScale != other.focusedDisabledScale) return false 288 289 return true 290 } 291 hashCodenull292 override fun hashCode(): Int { 293 var result = scale.hashCode() 294 result = 31 * result + focusedScale.hashCode() 295 result = 31 * result + pressedScale.hashCode() 296 result = 31 * result + disabledScale.hashCode() 297 result = 31 * result + focusedDisabledScale.hashCode() 298 299 return result 300 } 301 toStringnull302 override fun toString(): String { 303 return "ClickableSurfaceScale(scale=$scale, focusedScale=$focusedScale," + 304 "pressedScale=$pressedScale, disabledScale=$disabledScale, " + 305 "focusedDisabledScale=$focusedDisabledScale)" 306 } 307 308 companion object { 309 /** 310 * Signifies the absence of a scale in TV Components. Use this if you do not want to display 311 * a [ScaleIndication] in any of the Leanback TV Components. 312 */ 313 val None = 314 ClickableSurfaceScale( 315 scale = 1f, 316 focusedScale = 1f, 317 pressedScale = 1f, 318 disabledScale = 1f, 319 focusedDisabledScale = 1f 320 ) 321 } 322 } 323 324 /** 325 * Defines the scale for all TV [Interaction] states of selectable Surface. Note: This scale must be 326 * a non-negative float. 327 */ 328 @Immutable 329 class SelectableSurfaceScale 330 internal constructor( 331 @FloatRange(from = 0.0) internal val scale: Float, 332 @FloatRange(from = 0.0) internal val focusedScale: Float, 333 @FloatRange(from = 0.0) internal val pressedScale: Float, 334 @FloatRange(from = 0.0) internal val selectedScale: Float, 335 @FloatRange(from = 0.0) internal val disabledScale: Float, 336 @FloatRange(from = 0.0) internal val focusedSelectedScale: Float, 337 @FloatRange(from = 0.0) internal val focusedDisabledScale: Float, 338 @FloatRange(from = 0.0) internal val pressedSelectedScale: Float, 339 @FloatRange(from = 0.0) internal val selectedDisabledScale: Float, 340 @FloatRange(from = 0.0) internal val focusedSelectedDisabledScale: Float 341 ) { equalsnull342 override fun equals(other: Any?): Boolean { 343 if (this === other) return true 344 if (other == null || this::class != other::class) return false 345 346 other as SelectableSurfaceScale 347 348 if (scale != other.scale) return false 349 if (focusedScale != other.focusedScale) return false 350 if (pressedScale != other.pressedScale) return false 351 if (selectedScale != other.selectedScale) return false 352 if (disabledScale != other.disabledScale) return false 353 if (focusedSelectedScale != other.focusedSelectedScale) return false 354 if (focusedDisabledScale != other.focusedDisabledScale) return false 355 if (pressedSelectedScale != other.pressedSelectedScale) return false 356 if (selectedDisabledScale != other.selectedDisabledScale) return false 357 if (focusedSelectedDisabledScale != other.focusedSelectedDisabledScale) return false 358 359 return true 360 } 361 hashCodenull362 override fun hashCode(): Int { 363 var result = scale.hashCode() 364 result = 31 * result + focusedScale.hashCode() 365 result = 31 * result + pressedScale.hashCode() 366 result = 31 * result + selectedScale.hashCode() 367 result = 31 * result + disabledScale.hashCode() 368 result = 31 * result + focusedSelectedScale.hashCode() 369 result = 31 * result + focusedDisabledScale.hashCode() 370 result = 31 * result + pressedSelectedScale.hashCode() 371 result = 31 * result + selectedDisabledScale.hashCode() 372 result = 31 * result + focusedSelectedDisabledScale.hashCode() 373 374 return result 375 } 376 toStringnull377 override fun toString(): String { 378 return "SelectableSurfaceScale(scale=$scale, focusedScale=$focusedScale," + 379 "pressedScale=$pressedScale, selectedScale=$selectedScale," + 380 "disabledScale=$disabledScale, focusedSelectedScale=$focusedSelectedScale, " + 381 "focusedDisabledScale=$focusedDisabledScale," + 382 "pressedSelectedScale=$pressedSelectedScale, " + 383 "selectedDisabledScale=$selectedDisabledScale, " + 384 "focusedSelectedDisabledScale=$focusedSelectedDisabledScale)" 385 } 386 387 companion object { 388 /** Signifies the absence of a [ScaleIndication] in selectable surface. */ 389 val None = 390 SelectableSurfaceScale( 391 scale = 1f, 392 focusedScale = 1f, 393 pressedScale = 1f, 394 selectedScale = 1f, 395 disabledScale = 1f, 396 focusedSelectedScale = 1f, 397 focusedDisabledScale = 1f, 398 pressedSelectedScale = 1f, 399 selectedDisabledScale = 1f, 400 focusedSelectedDisabledScale = 1f 401 ) 402 } 403 } 404 405 /** Defines [Border] for all TV states of [Surface]. */ 406 @Immutable 407 class ClickableSurfaceBorder 408 internal constructor( 409 internal val border: Border, 410 internal val focusedBorder: Border, 411 internal val pressedBorder: Border, 412 internal val disabledBorder: Border, 413 internal val focusedDisabledBorder: Border 414 ) { equalsnull415 override fun equals(other: Any?): Boolean { 416 if (this === other) return true 417 if (other == null || this::class != other::class) return false 418 419 other as ClickableSurfaceBorder 420 421 if (border != other.border) return false 422 if (focusedBorder != other.focusedBorder) return false 423 if (pressedBorder != other.pressedBorder) return false 424 if (disabledBorder != other.disabledBorder) return false 425 if (focusedDisabledBorder != other.focusedDisabledBorder) return false 426 427 return true 428 } 429 hashCodenull430 override fun hashCode(): Int { 431 var result = border.hashCode() 432 result = 31 * result + focusedBorder.hashCode() 433 result = 31 * result + pressedBorder.hashCode() 434 result = 31 * result + disabledBorder.hashCode() 435 result = 31 * result + focusedDisabledBorder.hashCode() 436 437 return result 438 } 439 toStringnull440 override fun toString(): String { 441 return "ClickableSurfaceBorder(border=$border, " + 442 "focusedBorder=$focusedBorder, " + 443 "pressedBorder=$pressedBorder, " + 444 "disabledBorder=$disabledBorder, " + 445 "focusedDisabledBorder=$focusedDisabledBorder)" 446 } 447 } 448 449 /** Defines [Border] for all TV states of a selectable Surface. */ 450 @Immutable 451 class SelectableSurfaceBorder 452 internal constructor( 453 internal val border: Border, 454 internal val focusedBorder: Border, 455 internal val pressedBorder: Border, 456 internal val selectedBorder: Border, 457 internal val disabledBorder: Border, 458 internal val focusedSelectedBorder: Border, 459 internal val focusedDisabledBorder: Border, 460 internal val pressedSelectedBorder: Border, 461 internal val selectedDisabledBorder: Border, 462 internal val focusedSelectedDisabledBorder: Border 463 ) { equalsnull464 override fun equals(other: Any?): Boolean { 465 if (this === other) return true 466 if (other == null || this::class != other::class) return false 467 468 other as SelectableSurfaceBorder 469 470 if (border != other.border) return false 471 if (focusedBorder != other.focusedBorder) return false 472 if (pressedBorder != other.pressedBorder) return false 473 if (selectedBorder != other.selectedBorder) return false 474 if (disabledBorder != other.disabledBorder) return false 475 if (focusedSelectedBorder != other.focusedSelectedBorder) return false 476 if (focusedDisabledBorder != other.focusedDisabledBorder) return false 477 if (pressedSelectedBorder != other.pressedSelectedBorder) return false 478 if (selectedDisabledBorder != other.selectedDisabledBorder) return false 479 if (focusedSelectedDisabledBorder != other.focusedSelectedDisabledBorder) return false 480 481 return true 482 } 483 hashCodenull484 override fun hashCode(): Int { 485 var result = border.hashCode() 486 result = 31 * result + focusedBorder.hashCode() 487 result = 31 * result + pressedBorder.hashCode() 488 result = 31 * result + selectedBorder.hashCode() 489 result = 31 * result + disabledBorder.hashCode() 490 result = 31 * result + focusedSelectedBorder.hashCode() 491 result = 31 * result + focusedDisabledBorder.hashCode() 492 result = 31 * result + pressedSelectedBorder.hashCode() 493 result = 31 * result + selectedDisabledBorder.hashCode() 494 result = 31 * result + focusedSelectedDisabledBorder.hashCode() 495 496 return result 497 } 498 toStringnull499 override fun toString(): String { 500 return "SelectableSurfaceBorder(border=$border, focusedBorder=$focusedBorder," + 501 "pressedBorder=$pressedBorder, selectedBorder=$selectedBorder," + 502 "disabledBorder=$disabledBorder, focusedSelectedBorder=$focusedSelectedBorder, " + 503 "focusedDisabledBorder=$focusedDisabledBorder," + 504 "pressedSelectedBorder=$pressedSelectedBorder, " + 505 "selectedDisabledBorder=$selectedDisabledBorder, " + 506 "focusedSelectedDisabledBorder=$focusedSelectedDisabledBorder)" 507 } 508 } 509 510 /** Defines [Glow] for all TV [Interaction] states of [Surface]. */ 511 @Immutable 512 class ClickableSurfaceGlow 513 internal constructor( 514 internal val glow: Glow, 515 internal val focusedGlow: Glow, 516 internal val pressedGlow: Glow 517 ) { equalsnull518 override fun equals(other: Any?): Boolean { 519 if (this === other) return true 520 if (other == null || this::class != other::class) return false 521 522 other as ClickableSurfaceGlow 523 524 if (glow != other.glow) return false 525 if (focusedGlow != other.focusedGlow) return false 526 if (pressedGlow != other.pressedGlow) return false 527 528 return true 529 } 530 hashCodenull531 override fun hashCode(): Int { 532 var result = glow.hashCode() 533 result = 31 * result + focusedGlow.hashCode() 534 result = 31 * result + pressedGlow.hashCode() 535 536 return result 537 } 538 toStringnull539 override fun toString(): String { 540 return "ClickableSurfaceGlow(glow=$glow, focusedGlow=$focusedGlow, " + 541 "pressedGlow=$pressedGlow)" 542 } 543 } 544 545 /** Defines [Glow] for all TV [Interaction] states of a selectable Surface. */ 546 @Immutable 547 class SelectableSurfaceGlow 548 internal constructor( 549 internal val glow: Glow, 550 internal val focusedGlow: Glow, 551 internal val pressedGlow: Glow, 552 internal val selectedGlow: Glow, 553 internal val focusedSelectedGlow: Glow, 554 internal val pressedSelectedGlow: Glow 555 ) { equalsnull556 override fun equals(other: Any?): Boolean { 557 if (this === other) return true 558 if (other == null || this::class != other::class) return false 559 560 other as SelectableSurfaceGlow 561 562 if (glow != other.glow) return false 563 if (focusedGlow != other.focusedGlow) return false 564 if (pressedGlow != other.pressedGlow) return false 565 if (selectedGlow != other.selectedGlow) return false 566 if (focusedSelectedGlow != other.focusedSelectedGlow) return false 567 if (pressedSelectedGlow != other.pressedSelectedGlow) return false 568 569 return true 570 } 571 hashCodenull572 override fun hashCode(): Int { 573 var result = glow.hashCode() 574 result = 31 * result + focusedGlow.hashCode() 575 result = 31 * result + pressedGlow.hashCode() 576 result = 31 * result + selectedGlow.hashCode() 577 result = 31 * result + focusedSelectedGlow.hashCode() 578 result = 31 * result + pressedSelectedGlow.hashCode() 579 580 return result 581 } 582 toStringnull583 override fun toString(): String { 584 return "SelectableSurfaceGlow(glow=$glow, focusedGlow=$focusedGlow," + 585 "pressedGlow=$pressedGlow, selectedGlow=$selectedGlow," + 586 "focusedSelectedGlow=$focusedSelectedGlow, pressedSelectedGlow=$pressedSelectedGlow)" 587 } 588 } 589 590 /** Defines the container & content color [Color] for a non interactive surface. */ 591 @Immutable 592 class SurfaceColors 593 internal constructor(internal val containerColor: Color, internal val contentColor: Color) { equalsnull594 override fun equals(other: Any?): Boolean { 595 if (this === other) return true 596 if (other == null || this::class != other::class) return false 597 598 other as SurfaceColors 599 600 if (containerColor != other.containerColor) return false 601 if (contentColor != other.contentColor) return false 602 603 return true 604 } 605 hashCodenull606 override fun hashCode(): Int { 607 var result = containerColor.hashCode() 608 result = 31 * result + contentColor.hashCode() 609 return result 610 } 611 toStringnull612 override fun toString(): String { 613 return "SurfaceColors(containerColor=$containerColor, " + "contentColor=$contentColor)" 614 } 615 } 616