Skip to content

Commit

Permalink
Add comments on new controls widgets (#382)
Browse files Browse the repository at this point in the history
Fixes #374
  • Loading branch information
Jupi007 committed Nov 11, 2022
1 parent 8c21ea0 commit db6d3d7
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 38 deletions.
100 changes: 94 additions & 6 deletions lib/src/controls/yaru_checkbox.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,113 @@
import 'package:flutter/material.dart';

import '../constants.dart';
import 'yaru_check_button.dart';
import 'yaru_radio.dart';
import 'yaru_switch.dart';
import 'yaru_togglable.dart';

const _kCheckboxBorderRadius = Radius.circular(4);
const _kCheckboxDashStroke = 2.0;
const _kDashSizeFactor = 0.52;

class YaruCheckbox extends YaruTogglable<bool?> {
/// A Yaru checkbox.
///
/// The checkbox itself does not maintain any state. Instead, when the state of
/// the checkbox changes, the widget calls the [onChanged] callback. Most
/// widgets that use a checkbox will listen for the [onChanged] callback and
/// rebuild the checkbox with a new [value] to update the visual appearance of
/// the checkbox.
///
/// The checkbox can optionally display three values - true, false, and null -
/// if [tristate] is true. When [value] is null a dash is displayed. By default
/// [tristate] is false and the checkbox's [value] must be true or false.
///
/// See also:
///
/// * [YaruCheckButton], a desktop style check button with an interactive label.
/// * [YaruSwitch], a widget with semantics similar to [Checkbox].
/// * [YaruRadio], for selecting among a set of explicit values.
/// * [Slider], for selecting a value in a range.
class YaruCheckbox extends StatefulWidget implements YaruTogglable<bool?> {
/// A Yaru checkbox.
///
/// The checkbox itself does not maintain any state. Instead, when the state of
/// the checkbox changes, the widget calls the [onChanged] callback. Most
/// widgets that use a checkbox will listen for the [onChanged] callback and
/// rebuild the checkbox with a new [value] to update the visual appearance of
/// the checkbox.
const YaruCheckbox({
super.key,
required super.value,
super.tristate,
required super.onChanged,
super.focusNode,
super.autofocus,
required this.value,
this.tristate = false,
required this.onChanged,
this.focusNode,
this.autofocus = false,
}) : assert(tristate || value != null);

/// Whether this checkbox is checked.
///
/// This property must not be null.
@override
final bool? value;

/// If true the checkbox's [value] can be true, false, or null.
///
/// Checkbox displays a dash when its value is null.
///
/// When a tri-state checkbox ([tristate] is true) is tapped, its [onChanged]
/// callback will be applied to true if the current value is false, to null if
/// value is true, and to false if value is null (i.e. it cycles through false
/// => true => null => false when tapped).
///
/// If tristate is false (the default), [value] must not be null.
@override
final bool tristate;

@override
bool? get checked => value;

/// Called when the value of the checkbox should change.
///
/// The checkbox passes the new value to the callback but does not actually
/// change state until the parent widget rebuilds the checkbox with the new
/// value.
///
/// If this callback is null, the checkbox will be displayed as disabled
/// and will not respond to input gestures.
///
/// When the checkbox is tapped, if [tristate] is false (the default) then
/// the [onChanged] callback will be applied to `!value`. If [tristate] is
/// true this callback cycle from false to true to null.
///
/// The callback provided to [onChanged] should update the state of the parent
/// [StatefulWidget] using the [State.setState] method, so that the parent
/// gets rebuilt; for example:
///
/// ```dart
/// YaruCheckbox(
/// value: _throwShotAway,
/// onChanged: (bool? newValue) {
/// setState(() {
/// _throwShotAway = newValue!;
/// });
/// },
/// )
/// ```
@override
final ValueChanged<bool?>? onChanged;

@override
bool get interactive => onChanged != null;

/// {@macro flutter.widgets.Focus.focusNode}
@override
final FocusNode? focusNode;

/// {@macro flutter.widgets.Focus.autofocus}
@override
final bool autofocus;

@override
YaruTogglableState<YaruCheckbox> createState() {
return _YaruCheckboxState();
Expand Down
109 changes: 102 additions & 7 deletions lib/src/controls/yaru_radio.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,122 @@
import 'package:flutter/material.dart';

import '../constants.dart';
import 'yaru_checkbox.dart';
import 'yaru_radio_button.dart';
import 'yaru_switch.dart';
import 'yaru_togglable.dart';

const _kDotSizeFactor = 0.4;

class YaruRadio<T> extends YaruTogglable<T?> {
/// A Yaru radio.
///
/// Used to select between a number of mutually exclusive values. When one radio
/// button in a group is selected, the other radio buttons in the group cease to
/// be selected. The values are of type [T], the type parameter of the [YaruRadio]
/// class. Enums are commonly used for this purpose.
///
/// The radio button itself does not maintain any state. Instead, selecting the
/// radio invokes the [onChanged] callback, passing [value] as a parameter. If
/// [groupValue] and [value] match, this radio will be selected. Most widgets
/// will respond to [onChanged] by calling [State.setState] to update the
/// radio button's [groupValue].
///
/// See also:
///
/// * [YaruRadioButton], a desktop style radio button with an interactive label.
/// * [Slider], for selecting a value in a range.
/// * [YaruCheckbox] and [YaruSwitch], for toggling a particular value on or off.
class YaruRadio<T> extends StatefulWidget implements YaruTogglable<T?> {
/// Create a Yaru radio.
///
/// The radio button itself does not maintain any state. Instead, selecting the
/// radio invokes the [onChanged] callback, passing [value] as a parameter. If
/// [groupValue] and [value] match, this radio will be selected. Most widgets
/// will respond to [onChanged] by calling [State.setState] to update the
/// radio button's [groupValue].
const YaruRadio({
super.key,
required super.value,
required this.value,
required this.groupValue,
this.toggleable = false,
required super.onChanged,
super.focusNode,
super.autofocus,
required this.onChanged,
this.focusNode,
this.autofocus = false,
}) : assert(toggleable || value != null);

final bool toggleable;
/// The value represented by this radio button.
@override
final T value;

/// The currently selected value for a group of radio buttons.
///
/// This radio button is considered selected if its [value] matches the
/// [groupValue].
final T? groupValue;

@override
bool get checked => value == groupValue;

final T? groupValue;
/// Set to true if this radio button is allowed to be returned to an
/// indeterminate state by selecting it again when selected.
///
/// To indicate returning to an indeterminate state, [onChanged] will be
/// called with null.
///
/// If true, [onChanged] can be called with [value] when selected while
/// [groupValue] != [value], or with null when selected again while
/// [groupValue] == [value].
///
/// If false, [onChanged] will be called with [value] when it is selected
/// while [groupValue] != [value], and only by selecting another radio button
/// in the group (i.e. changing the value of [groupValue]) can this radio
/// button be unselected.
///
/// The default is false.
final bool toggleable;

@override
bool get tristate => toggleable;

/// Called when the user selects this radio button.
///
/// The radio button passes [value] as a parameter to this callback. The radio
/// button does not actually change state until the parent widget rebuilds the
/// radio button with the new [groupValue].
///
/// If null, the radio button will be displayed as disabled.
///
/// The provided callback will not be invoked if this radio button is already
/// selected.
///
/// The callback provided to [onChanged] should update the state of the parent
/// [StatefulWidget] using the [State.setState] method, so that the parent
/// gets rebuilt; for example:
///
/// ```dart
/// YaruRadio<SingingCharacter>(
/// value: SingingCharacter.lafayette,
/// groupValue: _character,
/// onChanged: (SingingCharacter newValue) {
/// setState(() {
/// _character = newValue;
/// });
/// },
/// )
/// ```
@override
final ValueChanged<T?>? onChanged;

@override
bool get interactive => onChanged != null;

/// {@macro flutter.widgets.Focus.focusNode}
@override
final FocusNode? focusNode;

/// {@macro flutter.widgets.Focus.autofocus}
@override
final bool autofocus;

@override
YaruTogglableState<YaruRadio<T?>> createState() {
Expand Down
75 changes: 70 additions & 5 deletions lib/src/controls/yaru_switch.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,92 @@
import 'package:flutter/material.dart';

import 'yaru_checkbox.dart';
import 'yaru_radio.dart';
import 'yaru_switch_button.dart';
import 'yaru_togglable.dart';

const _kSwitchActivableAreaPadding =
EdgeInsets.symmetric(horizontal: 2, vertical: 5);
const _kSwitchSize = Size(55, 30);
const _kSwitchDotSizeFactor = 0.8;

class YaruSwitch extends YaruTogglable<bool> {
/// A Yaru switch.
///
/// Used to toggle the on/off state of a single setting.
///
/// The switch itself does not maintain any state. Instead, when the state of
/// the switch changes, the widget calls the [onChanged] callback. Most widgets
/// that use a switch will listen for the [onChanged] callback and rebuild the
/// switch with a new [value] to update the visual appearance of the switch.
///
/// If the [onChanged] callback is null, then the switch will be disabled (it
/// will not respond to input). A disabled switch's thumb and track are rendered
/// in shades of grey by default. The default appearance of a disabled switch
/// can be overridden with [inactiveThumbColor] and [inactiveTrackColor].
///
/// See also:
///
/// * [YaruSwitchButton], a desktop style switch button with an interactive label.
/// * [YaruCheckbox], another widget with similar semantics.
/// * [YaruRadio], for selecting among a set of explicit values.
/// * [Slider], for selecting a value in a range.
class YaruSwitch extends StatefulWidget implements YaruTogglable<bool> {
const YaruSwitch({
super.key,
required super.value,
required super.onChanged,
super.focusNode,
super.autofocus,
required this.value,
required this.onChanged,
this.focusNode,
this.autofocus = false,
});

/// Whether this switch is on or off.
///
/// This property must not be null.
@override
final bool value;

@override
bool get checked => value;

@override
bool get tristate => false;

/// Called when the user toggles the switch on or off.
///
/// The switch passes the new value to the callback but does not actually
/// change state until the parent widget rebuilds the switch with the new
/// value.
///
/// If null, the switch will be displayed as disabled.
///
/// The callback provided to [onChanged] should update the state of the parent
/// [StatefulWidget] using the [State.setState] method, so that the parent
/// gets rebuilt; for example:
///
/// ```dart
/// YaruSwitch(
/// value: _giveVerse,
/// onChanged: (bool newValue) {
/// setState(() {
/// _giveVerse = newValue;
/// });
/// },
/// )
/// ```
@override
final ValueChanged<bool>? onChanged;

@override
bool get interactive => onChanged != null;

/// {@macro flutter.widgets.Focus.focusNode}
@override
final FocusNode? focusNode;

/// {@macro flutter.widgets.Focus.autofocus}
@override
final bool autofocus;

@override
YaruTogglableState<YaruSwitch> createState() {
return _YaruSwitchState();
Expand Down
Loading

0 comments on commit db6d3d7

Please sign in to comment.